| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package util |
| |
| import ( |
| "regexp" |
| "strings" |
| |
| wire "v.io/syncbase/v23/services/syncbase" |
| "v.io/v23/context" |
| "v.io/v23/security/access" |
| "v.io/v23/verror" |
| ) |
| |
| // TODO(sadovsky): Expand the allowed charset. We should probably switch to a |
| // blacklist, reserving just a few special chars like '\0', '*', and '/' but |
| // otherwise allowing all valid UTF-8 strings. |
| var nameRegexp *regexp.Regexp = regexp.MustCompile("^[a-zA-Z0-9_.-]+$") |
| |
| // ValidName returns true iff the given Syncbase component name is valid. |
| func ValidName(s string) bool { |
| return nameRegexp.MatchString(s) |
| } |
| |
| // ParseTableRowPair splits the given pattern of the form 'table/row' into |
| // the table part and the row part. The row part might be empty. |
| func ParseTableRowPair(ctx *context.T, pattern string) (string, string, error) { |
| parts := strings.Split(pattern, "/") |
| if len(parts) != 2 { |
| return "", "", verror.New(verror.ErrBadArg, ctx, pattern) |
| } |
| table, prefix := parts[0], parts[1] |
| if !ValidName(table) { |
| return "", "", verror.New(wire.ErrInvalidName, ctx, table) |
| } |
| if prefix != "" && !ValidName(prefix) { |
| return "", "", verror.New(wire.ErrInvalidName, ctx, prefix) |
| } |
| return table, prefix, nil |
| } |
| |
| // PrefixRangeStart returns the start of the row range for the given prefix. |
| func PrefixRangeStart(p string) string { |
| return p |
| } |
| |
| // PrefixRangeLimit returns the limit of the row range for the given prefix. |
| func PrefixRangeLimit(p string) string { |
| // A string is a []byte, i.e. can be thought of as a base-256 number. The code |
| // below effectively adds 1 to this number, then chops off any trailing \x00 |
| // bytes. If the input string consists entirely of \xff bytes, we return an |
| // empty string. |
| x := []byte(p) |
| for len(x) > 0 { |
| if x[len(x)-1] == 255 { |
| x = x[:len(x)-1] // chop off trailing \x00 |
| } else { |
| x[len(x)-1] += 1 // add 1 |
| break // no carry |
| } |
| } |
| return string(x) |
| } |
| |
| // AccessController provides access control for various syncbase objects. |
| type AccessController interface { |
| // SetPermissions replaces the current Permissions for an object. |
| // For detailed documentation, see Object.SetPermissions. |
| SetPermissions(ctx *context.T, perms access.Permissions, version string) error |
| |
| // GetPermissions returns the current Permissions for an object. |
| // For detailed documentation, see Object.GetPermissions. |
| GetPermissions(ctx *context.T) (perms access.Permissions, version string, err error) |
| } |