github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/internal/datastore/crdb/keys.go (about) 1 package crdb 2 3 import ( 4 "context" 5 "strings" 6 7 "github.com/authzed/authzed-go/pkg/requestmeta" 8 "google.golang.org/grpc/metadata" 9 ) 10 11 type keySet map[string]struct{} 12 13 func newKeySet(_ context.Context) keySet { 14 return make(map[string]struct{}) 15 } 16 17 type overlapKeyer interface { 18 addKey(keySet keySet, namespace string) 19 } 20 21 type keySetAddFunc func(keySet keySet, namespace string) 22 23 func (f keySetAddFunc) addKey(keySet keySet, namespace string) { 24 f(keySet, namespace) 25 } 26 27 var ( 28 noOverlapKeyer overlapKeyer = keySetAddFunc(noOverlap) 29 prefixKeyer overlapKeyer = keySetAddFunc(appendKeysFromNamespaceComponents) 30 _ overlapKeyer = appendStaticKey("") 31 ) 32 33 // noOverlap adds no keys to the overlap set 34 func noOverlap(_ keySet, _ string) {} 35 36 // appendStaticKey adds the same transaction overlap key for every namespace 37 func appendStaticKey(key string) keySetAddFunc { 38 return func(m keySet, _ string) { 39 m[key] = struct{}{} 40 } 41 } 42 43 // appendKeysFromNamespaceComponents adds an overlap key for namespace prefixes 44 // This should not be used in deployments where non-prefixed namespaces are 45 // allowed. 46 func appendKeysFromNamespaceComponents(keySet keySet, namespace string) { 47 keySet[prefix(namespace)] = struct{}{} 48 } 49 50 // prefix returns the first namespace prefix or the default overlap key 51 func prefix(s string) string { 52 prefix, _, ok := strings.Cut(s, "/") 53 if !ok { 54 return defaultOverlapKey 55 } 56 return prefix 57 } 58 59 // overlapKeysFromContext reads the request-provided initial overlap key set 60 // from the grpc request metadata. 61 func overlapKeysFromContext(ctx context.Context) keySet { 62 keys := newKeySet(ctx) 63 md, ok := metadata.FromIncomingContext(ctx) 64 if !ok { 65 return keys 66 } 67 68 for _, keyList := range md[string(requestmeta.RequestOverlapKey)] { 69 for _, key := range strings.Split(keyList, ",") { 70 key = strings.TrimSpace(key) 71 if len(key) > 0 { 72 keys[key] = struct{}{} 73 } 74 } 75 } 76 return keys 77 }