-
Notifications
You must be signed in to change notification settings - Fork 245
/
onr.go
111 lines (92 loc) · 3.1 KB
/
onr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package tuple
import (
"sort"
"strings"
"github.com/jzelinskie/stringz"
core "github.com/authzed/spicedb/pkg/proto/core/v1"
)
// ObjectAndRelation creates an ONR from string pieces.
func ObjectAndRelation(ns, oid, rel string) *core.ObjectAndRelation {
return &core.ObjectAndRelation{
Namespace: ns,
ObjectId: oid,
Relation: rel,
}
}
// RelationReference creates a RelationReference from the string pieces.
func RelationReference(namespaceName string, relationName string) *core.RelationReference {
return &core.RelationReference{
Namespace: namespaceName,
Relation: relationName,
}
}
// ParseSubjectONR converts a string representation of a Subject ONR to a proto object. Unlike
// ParseONR, this method allows for objects without relations. If an object without a relation
// is given, the relation will be set to ellipsis.
func ParseSubjectONR(subjectOnr string) *core.ObjectAndRelation {
groups := subjectRegex.FindStringSubmatch(subjectOnr)
if len(groups) == 0 {
return nil
}
relation := Ellipsis
subjectRelIndex := stringz.SliceIndex(subjectRegex.SubexpNames(), "subjectRel")
if len(groups[subjectRelIndex]) > 0 {
relation = groups[subjectRelIndex]
}
return &core.ObjectAndRelation{
Namespace: groups[stringz.SliceIndex(subjectRegex.SubexpNames(), "subjectType")],
ObjectId: groups[stringz.SliceIndex(subjectRegex.SubexpNames(), "subjectID")],
Relation: relation,
}
}
// ParseONR converts a string representation of an ONR to a proto object.
func ParseONR(onr string) *core.ObjectAndRelation {
groups := onrRegex.FindStringSubmatch(onr)
if len(groups) == 0 {
return nil
}
return &core.ObjectAndRelation{
Namespace: groups[stringz.SliceIndex(onrRegex.SubexpNames(), "resourceType")],
ObjectId: groups[stringz.SliceIndex(onrRegex.SubexpNames(), "resourceID")],
Relation: groups[stringz.SliceIndex(onrRegex.SubexpNames(), "resourceRel")],
}
}
// JoinRelRef joins the namespace and relation together into the same
// format as `StringRR()`.
func JoinRelRef(namespace, relation string) string { return namespace + "#" + relation }
// MustSplitRelRef splits a string produced by `JoinRelRef()` and panics if
// it fails.
func MustSplitRelRef(relRef string) (namespace, relation string) {
var ok bool
namespace, relation, ok = strings.Cut(relRef, "#")
if !ok {
panic("improperly formatted relation reference")
}
return
}
// StringRR converts a RR object to a string.
func StringRR(rr *core.RelationReference) string {
if rr == nil {
return ""
}
return JoinRelRef(rr.Namespace, rr.Relation)
}
// StringONR converts an ONR object to a string.
func StringONR(onr *core.ObjectAndRelation) string {
if onr == nil {
return ""
}
if onr.Relation == Ellipsis {
return JoinObjectRef(onr.Namespace, onr.ObjectId)
}
return JoinRelRef(JoinObjectRef(onr.Namespace, onr.ObjectId), onr.Relation)
}
// StringsONRs converts ONR objects to a string slice, sorted.
func StringsONRs(onrs []*core.ObjectAndRelation) []string {
onrstrings := make([]string, 0, len(onrs))
for _, onr := range onrs {
onrstrings = append(onrstrings, StringONR(onr))
}
sort.Strings(onrstrings)
return onrstrings
}