Skip to content

Commit b4920b4

Browse files
authored
Add a Relation attribute to QueryResult (for internal use) (#306)
1 parent 2251884 commit b4920b4

File tree

4 files changed

+45
-65
lines changed

4 files changed

+45
-65
lines changed

pkg/authz/query/resultset.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
type ResultSetNode struct {
2525
ObjectType string
2626
ObjectId string
27+
Relation string
2728
Warrant warrant.WarrantSpec
2829
IsImplicit bool
2930
next *ResultSetNode
@@ -47,16 +48,17 @@ func (rs *ResultSet) List() *ResultSetNode {
4748
return rs.head
4849
}
4950

50-
func (rs *ResultSet) Add(objectType string, objectId string, warrant warrant.WarrantSpec, isImplicit bool) {
51+
func (rs *ResultSet) Add(objectType string, objectId string, relation string, warrant warrant.WarrantSpec, isImplicit bool) {
5152
newNode := &ResultSetNode{
5253
ObjectType: objectType,
5354
ObjectId: objectId,
55+
Relation: relation,
5456
Warrant: warrant,
5557
IsImplicit: isImplicit,
5658
next: nil,
5759
}
5860

59-
existingRes, exists := rs.m[key(objectType, objectId)]
61+
existingRes, exists := rs.m[key(objectType, objectId, relation)]
6062
if !exists {
6163
// Add warrant to list
6264
if rs.head == nil {
@@ -72,35 +74,35 @@ func (rs *ResultSet) Add(objectType string, objectId string, warrant warrant.War
7274

7375
if !exists || (existingRes.IsImplicit && !isImplicit) {
7476
// Add result node to map for O(1) lookups
75-
rs.m[key(objectType, objectId)] = newNode
77+
rs.m[key(objectType, objectId, relation)] = newNode
7678
}
7779
}
7880

7981
func (rs *ResultSet) Len() int {
8082
return len(rs.m)
8183
}
8284

83-
func (rs *ResultSet) Get(objectType string, objectId string) *ResultSetNode {
84-
return rs.m[key(objectType, objectId)]
85+
func (rs *ResultSet) Get(objectType string, objectId string, relation string) *ResultSetNode {
86+
return rs.m[key(objectType, objectId, relation)]
8587
}
8688

87-
func (rs *ResultSet) Has(objectType string, objectId string) bool {
88-
_, exists := rs.m[key(objectType, objectId)]
89+
func (rs *ResultSet) Has(objectType string, objectId string, relation string) bool {
90+
_, exists := rs.m[key(objectType, objectId, relation)]
8991
return exists
9092
}
9193

9294
func (rs *ResultSet) Union(other *ResultSet) *ResultSet {
9395
resultSet := NewResultSet()
9496
for iter := rs.List(); iter != nil; iter = iter.Next() {
95-
resultSet.Add(iter.ObjectType, iter.ObjectId, iter.Warrant, iter.IsImplicit)
97+
resultSet.Add(iter.ObjectType, iter.ObjectId, iter.Relation, iter.Warrant, iter.IsImplicit)
9698
}
9799

98100
for iter := other.List(); iter != nil; iter = iter.Next() {
99101
isImplicit := iter.IsImplicit
100-
if resultSet.Has(iter.ObjectType, iter.ObjectId) {
101-
isImplicit = isImplicit && resultSet.Get(iter.ObjectType, iter.ObjectId).IsImplicit
102+
if resultSet.Has(iter.ObjectType, iter.ObjectId, iter.Relation) {
103+
isImplicit = isImplicit && resultSet.Get(iter.ObjectType, iter.ObjectId, iter.Relation).IsImplicit
102104
}
103-
resultSet.Add(iter.ObjectType, iter.ObjectId, iter.Warrant, isImplicit)
105+
resultSet.Add(iter.ObjectType, iter.ObjectId, iter.Relation, iter.Warrant, isImplicit)
104106
}
105107

106108
return resultSet
@@ -110,9 +112,9 @@ func (rs *ResultSet) Intersect(other *ResultSet) *ResultSet {
110112
resultSet := NewResultSet()
111113
for iter := rs.List(); iter != nil; iter = iter.Next() {
112114
isImplicit := iter.IsImplicit
113-
if other.Has(iter.ObjectType, iter.ObjectId) {
114-
isImplicit = isImplicit || other.Get(iter.ObjectType, iter.ObjectId).IsImplicit
115-
resultSet.Add(iter.ObjectType, iter.ObjectId, iter.Warrant, isImplicit)
115+
if other.Has(iter.ObjectType, iter.ObjectId, iter.Relation) {
116+
isImplicit = isImplicit || other.Get(iter.ObjectType, iter.ObjectId, iter.Relation).IsImplicit
117+
resultSet.Add(iter.ObjectType, iter.ObjectId, iter.Relation, iter.Warrant, isImplicit)
116118
}
117119
}
118120

@@ -122,7 +124,7 @@ func (rs *ResultSet) Intersect(other *ResultSet) *ResultSet {
122124
func (rs *ResultSet) String() string {
123125
var strs []string
124126
for iter := rs.List(); iter != nil; iter = iter.Next() {
125-
strs = append(strs, fmt.Sprintf("%s => %s", key(iter.ObjectType, iter.ObjectId), iter.Warrant.String()))
127+
strs = append(strs, fmt.Sprintf("%s => %s", key(iter.ObjectType, iter.ObjectId, iter.Relation), iter.Warrant.String()))
126128
}
127129

128130
return strings.Join(strs, ", ")
@@ -136,6 +138,6 @@ func NewResultSet() *ResultSet {
136138
}
137139
}
138140

139-
func key(objectType string, objectId string) string {
140-
return fmt.Sprintf("%s:%s", objectType, objectId)
141+
func key(objectType string, objectId string, relation string) string {
142+
return fmt.Sprintf("%s:%s#%s", objectType, objectId, relation)
141143
}

pkg/authz/query/service.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func (svc QueryService) Query(ctx context.Context, query Query, listParams servi
100100
}
101101

102102
for _, relation := range relations {
103-
res, err := svc.query(ctx, Query{
103+
queryResult, err := svc.query(ctx, Query{
104104
Expand: query.Expand,
105105
SelectObjects: &SelectObjects{
106106
ObjectTypes: []string{objectType.Type},
@@ -113,7 +113,9 @@ func (svc QueryService) Query(ctx context.Context, query Query, listParams servi
113113
return nil, nil, nil, err
114114
}
115115

116-
resultSet = resultSet.Union(res)
116+
for res := queryResult.List(); res != nil; res = res.Next() {
117+
resultSet.Add(res.ObjectType, res.ObjectId, relation, res.Warrant, res.IsImplicit)
118+
}
117119
}
118120
}
119121
case query.SelectSubjects != nil:
@@ -159,7 +161,7 @@ func (svc QueryService) Query(ctx context.Context, query Query, listParams servi
159161

160162
for _, subjectType := range subjectTypes {
161163
for _, relation := range relations {
162-
res, err := svc.query(ctx, Query{
164+
queryResult, err := svc.query(ctx, Query{
163165
Expand: query.Expand,
164166
SelectSubjects: &SelectSubjects{
165167
SubjectTypes: []string{subjectType.Type},
@@ -172,7 +174,9 @@ func (svc QueryService) Query(ctx context.Context, query Query, listParams servi
172174
return nil, nil, nil, err
173175
}
174176

175-
resultSet = resultSet.Union(res)
177+
for res := queryResult.List(); res != nil; res = res.Next() {
178+
resultSet.Add(res.ObjectType, res.ObjectId, relation, res.Warrant, res.IsImplicit)
179+
}
176180
}
177181
}
178182
default:
@@ -183,6 +187,7 @@ func (svc QueryService) Query(ctx context.Context, query Query, listParams servi
183187
queryResults = append(queryResults, QueryResult{
184188
ObjectType: res.ObjectType,
185189
ObjectId: res.ObjectId,
190+
Relation: res.Relation,
186191
Warrant: res.Warrant,
187192
IsImplicit: res.IsImplicit,
188193
})
@@ -358,17 +363,17 @@ func (svc QueryService) query(ctx context.Context, query Query, level int) (*Res
358363

359364
for _, w := range expandedWildcardWarrants {
360365
if w.ObjectId != warrant.Wildcard {
361-
resultSet.Add(w.ObjectType, w.ObjectId, matchedWarrant, level > 0)
366+
resultSet.Add(w.ObjectType, w.ObjectId, relation, matchedWarrant, level > 0)
362367
}
363368
}
364369
} else {
365-
resultSet.Add(matchedWarrant.ObjectType, matchedWarrant.ObjectId, matchedWarrant, level > 0)
370+
resultSet.Add(matchedWarrant.ObjectType, matchedWarrant.ObjectId, relation, matchedWarrant, level > 0)
366371
}
367372
}
368373
} else if query.SelectObjects.WhereSubject == nil ||
369374
(matchedWarrant.Subject.ObjectType == query.SelectObjects.WhereSubject.Type &&
370375
matchedWarrant.Subject.ObjectId == query.SelectObjects.WhereSubject.Id) {
371-
resultSet.Add(matchedWarrant.ObjectType, matchedWarrant.ObjectId, matchedWarrant, level > 0)
376+
resultSet.Add(matchedWarrant.ObjectType, matchedWarrant.ObjectId, relation, matchedWarrant, level > 0)
372377
}
373378
}
374379

@@ -425,10 +430,10 @@ func (svc QueryService) query(ctx context.Context, query Query, level int) (*Res
425430
}
426431

427432
for res := userset.List(); res != nil; res = res.Next() {
428-
resultSet.Add(res.ObjectType, res.ObjectId, matchedWarrant, level > 0)
433+
resultSet.Add(res.ObjectType, res.ObjectId, relation, matchedWarrant, level > 0)
429434
}
430435
} else if query.SelectSubjects.SubjectTypes[0] == matchedWarrant.Subject.ObjectType {
431-
resultSet.Add(matchedWarrant.Subject.ObjectType, matchedWarrant.Subject.ObjectId, matchedWarrant, level > 0)
436+
resultSet.Add(matchedWarrant.Subject.ObjectType, matchedWarrant.Subject.ObjectId, relation, matchedWarrant, level > 0)
432437
}
433438
}
434439

pkg/authz/query/spec.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ type QueryHaving struct {
9797
type QueryResult struct {
9898
ObjectType string `json:"objectType"`
9999
ObjectId string `json:"objectId"`
100+
Relation string `json:"-"`
100101
Warrant baseWarrant.WarrantSpec `json:"warrant"`
101102
IsImplicit bool `json:"isImplicit"`
102103
Meta map[string]interface{} `json:"meta,omitempty"`

tests/v1/query.json

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,10 +1460,10 @@
14601460
}
14611461
},
14621462
{
1463-
"name": "selectMembersOrViewersOfTypeUserForDocumentD5Limit3SortOrderDesc",
1463+
"name": "selectExplicitOwnersOrViewersOfTypeUserForDocumentF3Limit1SortOrderDesc",
14641464
"request": {
14651465
"method": "GET",
1466-
"url": "/v1/query?q=select%20member%2Cviewer%20of%20type%20user%20for%20document:D5&limit=3&sortOrder=DESC",
1466+
"url": "/v1/query?q=select%20explicit%20owner%2Cviewer%20of%20type%20user%20for%20document:F3&limit=1&sortOrder=DESC",
14671467
"headers": {
14681468
"Warrant-Token": "latest"
14691469
}
@@ -1485,46 +1485,18 @@
14851485
"relation": "member"
14861486
}
14871487
},
1488-
"isImplicit": true
1489-
},
1490-
{
1491-
"objectType": "user",
1492-
"objectId": "U3",
1493-
"warrant": {
1494-
"objectType": "document",
1495-
"objectId": "F3",
1496-
"relation": "viewer",
1497-
"subject": {
1498-
"objectType": "user",
1499-
"objectId": "U3"
1500-
}
1501-
},
1502-
"isImplicit": true
1503-
},
1504-
{
1505-
"objectType": "user",
1506-
"objectId": "U2",
1507-
"warrant": {
1508-
"objectType": "document",
1509-
"objectId": "F2",
1510-
"relation": "editor",
1511-
"subject": {
1512-
"objectType": "user",
1513-
"objectId": "U2"
1514-
}
1515-
},
1516-
"isImplicit": true
1488+
"isImplicit": false
15171489
}
15181490
],
1519-
"lastId": "{{ selectMembersOrViewersOfTypeUserForDocumentD5Limit3SortOrderDesc.lastId }}"
1491+
"lastId": "{{ selectExplicitOwnersOrViewersOfTypeUserForDocumentF3Limit1SortOrderDesc.lastId }}"
15201492
}
15211493
}
15221494
},
15231495
{
1524-
"name": "selectMembersOrViewersOfTypeUserLimit3SortOrderDescAfterId1",
1496+
"name": "selectExplicitOwnersOrViewersOfTypeUserForDocumentF3Limit1SortOrderDescAfterId1",
15251497
"request": {
15261498
"method": "GET",
1527-
"url": "/v1/query?q=select%20member%2Cviewer%20of%20type%20user%20for%20document:D5&limit=3&sortOrder=DESC&lastId={{ selectMembersOrViewersOfTypeUserForDocumentD5Limit3SortOrderDesc.lastId }}",
1499+
"url": "/v1/query?q=select%20explicit%20owner%2Cviewer%20of%20type%20user%20for%20document:F3&limit=3&sortOrder=DESC&lastId={{ selectExplicitOwnersOrViewersOfTypeUserForDocumentF3Limit1SortOrderDesc.lastId }}",
15281500
"headers": {
15291501
"Warrant-Token": "latest"
15301502
}
@@ -1535,17 +1507,17 @@
15351507
"results": [
15361508
{
15371509
"objectType": "user",
1538-
"objectId": "U1",
1510+
"objectId": "U3",
15391511
"warrant": {
15401512
"objectType": "document",
1541-
"objectId": "F1",
1542-
"relation": "owner",
1513+
"objectId": "F3",
1514+
"relation": "viewer",
15431515
"subject": {
15441516
"objectType": "user",
1545-
"objectId": "U1"
1517+
"objectId": "U3"
15461518
}
15471519
},
1548-
"isImplicit": true
1520+
"isImplicit": false
15491521
}
15501522
]
15511523
}

0 commit comments

Comments
 (0)