open-vault/helper/namespace/namespace.go
2018-08-10 12:13:11 -04:00

108 lines
2 KiB
Go

package namespace
import (
"context"
"errors"
"strings"
)
type nsContext struct {
context.Context
// Note: this is currently not locked because we think all uses will take
// place within a single goroutine. If that isn't the case, this should be
// protected by an atomic.Value.
cachedNS *Namespace
}
type contextValues struct{}
const (
RootNamespaceID = "root"
)
var (
contextNamespace contextValues = struct{}{}
ErrNoNamespace error = errors.New("no namespace")
)
type Namespace struct {
ID string `json:"id"`
Path string `json:"path"`
}
func New(id, path string) *Namespace {
return &Namespace{
ID: id,
Path: path,
}
}
func (n *Namespace) HasParent(possibleParent *Namespace) bool {
switch {
case n.Path == "":
return false
case possibleParent.Path == "":
return true
default:
return strings.HasPrefix(n.Path, possibleParent.Path)
}
}
func (n *Namespace) TrimmedPath(path string) string {
return strings.TrimPrefix(path, n.Path)
}
func ContextWithNamespace(ctx context.Context, ns *Namespace) context.Context {
nsCtx := context.WithValue(ctx, contextNamespace, ns)
return &nsContext{
Context: nsCtx,
cachedNS: ns,
}
}
func FromContext(ctx context.Context) (*Namespace, error) {
if ctx == nil {
return nil, errors.New("context was nil")
}
nsCtx, ok := ctx.(*nsContext)
if ok {
if nsCtx.cachedNS != nil {
return nsCtx.cachedNS, nil
}
}
ns := ctx.Value(contextNamespace)
if ns == nil {
return nil, ErrNoNamespace
}
if ok {
nsCtx.cachedNS = ns.(*Namespace)
}
return ns.(*Namespace), nil
}
func TestContext() context.Context {
return ContextWithNamespace(context.Background(), New(RootNamespaceID, ""))
}
// Canonicalize trims any prefix '/' and adds a trailing '/' to the
// provided string
func Canonicalize(nsPath string) string {
if nsPath == "" {
return ""
}
// Canonicalize the path to not have a '/' prefix
nsPath = strings.TrimPrefix(nsPath, "/")
// Canonicalize the path to always having a '/' suffix
if !strings.HasSuffix(nsPath, "/") {
nsPath += "/"
}
return nsPath
}