+1
-1
appview/oauth/handler/handler.go
+1
-1
appview/oauth/handler/handler.go
···
336
336
defaultKnot := "knot1.tangled.sh"
337
337
338
338
log.Printf("adding %s to default knot", did)
339
-
err := o.enforcer.AddMember(defaultKnot, did)
339
+
err := o.enforcer.AddKnotMember(defaultKnot, did)
340
340
if err != nil {
341
341
log.Println("failed to add user to knot1.tangled.sh: ", err)
342
342
return
+1
-1
appview/repo/repo.go
+1
-1
appview/repo/repo.go
···
1090
1090
switch r.Method {
1091
1091
case http.MethodGet:
1092
1092
user := rp.oauth.GetUser(r)
1093
-
knots, err := rp.enforcer.GetDomainsForUser(user.Did)
1093
+
knots, err := rp.enforcer.GetKnotsForUser(user.Did)
1094
1094
if err != nil {
1095
1095
rp.pages.Notice(w, "repo", "Invalid user account.")
1096
1096
return
+1
-1
appview/state/knotstream.go
+1
-1
appview/state/knotstream.go
+5
-5
appview/state/state.go
+5
-5
appview/state/state.go
···
336
336
}
337
337
338
338
// add basic acls for this domain
339
-
err = s.enforcer.AddDomain(domain)
339
+
err = s.enforcer.AddKnot(domain)
340
340
if err != nil {
341
341
log.Println("failed to setup owner of domain", err)
342
342
http.Error(w, err.Error(), http.StatusInternalServerError)
···
344
344
}
345
345
346
346
// add this did as owner of this domain
347
-
err = s.enforcer.AddOwner(domain, reg.ByDid)
347
+
err = s.enforcer.AddKnotOwner(domain, reg.ByDid)
348
348
if err != nil {
349
349
log.Println("failed to setup owner of domain", err)
350
350
http.Error(w, err.Error(), http.StatusInternalServerError)
···
409
409
}
410
410
}
411
411
412
-
ok, err := s.enforcer.IsServerOwner(user.Did, domain)
412
+
ok, err := s.enforcer.IsKnotOwner(user.Did, domain)
413
413
isOwner := err == nil && ok
414
414
415
415
p := pages.KnotParams{
···
528
528
return
529
529
}
530
530
531
-
err = s.enforcer.AddMember(domain, subjectIdentity.DID.String())
531
+
err = s.enforcer.AddKnotMember(domain, subjectIdentity.DID.String())
532
532
if err != nil {
533
533
w.Write([]byte(fmt.Sprint("failed to add member: ", err)))
534
534
return
···
576
576
switch r.Method {
577
577
case http.MethodGet:
578
578
user := s.oauth.GetUser(r)
579
-
knots, err := s.enforcer.GetDomainsForUser(user.Did)
579
+
knots, err := s.enforcer.GetKnotsForUser(user.Did)
580
580
if err != nil {
581
581
s.pages.Notice(w, "repo", "Invalid user account.")
582
582
return
-4
knotclient/events.go
-4
knotclient/events.go
+1
-1
knotserver/handler.go
+1
-1
knotserver/handler.go
+1
-1
knotserver/jetstream.go
+1
-1
knotserver/jetstream.go
···
43
43
return fmt.Errorf("failed to enforce permissions: %w", err)
44
44
}
45
45
46
-
if err := h.e.AddMember(ThisServer, record.Subject); err != nil {
46
+
if err := h.e.AddKnotMember(ThisServer, record.Subject); err != nil {
47
47
l.Error("failed to add member", "error", err)
48
48
return fmt.Errorf("failed to add member: %w", err)
49
49
}
+2
-2
knotserver/routes.go
+2
-2
knotserver/routes.go
···
1177
1177
}
1178
1178
h.jc.AddDid(did)
1179
1179
1180
-
if err := h.e.AddMember(ThisServer, did); err != nil {
1180
+
if err := h.e.AddKnotMember(ThisServer, did); err != nil {
1181
1181
l.Error("adding member", "error", err.Error())
1182
1182
writeError(w, err.Error(), http.StatusInternalServerError)
1183
1183
return
···
1312
1312
}
1313
1313
h.jc.AddDid(data.Did)
1314
1314
1315
-
if err := h.e.AddOwner(ThisServer, data.Did); err != nil {
1315
+
if err := h.e.AddKnotOwner(ThisServer, data.Did); err != nil {
1316
1316
l.Error("adding owner", "error", err.Error())
1317
1317
writeError(w, err.Error(), http.StatusInternalServerError)
1318
1318
return
+79
-27
rbac/rbac.go
+79
-27
rbac/rbac.go
···
2
2
3
3
import (
4
4
"database/sql"
5
-
"fmt"
5
+
"slices"
6
6
"strings"
7
7
8
8
adapter "github.com/Blank-Xu/sql-adapter"
···
59
59
return &Enforcer{e}, nil
60
60
}
61
61
62
-
func (e *Enforcer) AddDomain(domain string) error {
62
+
func (e *Enforcer) AddKnot(knot string) error {
63
63
// Add policies with patterns
64
64
_, err := e.E.AddPolicies([][]string{
65
-
{"server:owner", domain, domain, "server:invite"},
66
-
{"server:member", domain, domain, "repo:create"},
65
+
{"server:owner", knot, knot, "server:invite"},
66
+
{"server:member", knot, knot, "repo:create"},
67
+
})
68
+
if err != nil {
69
+
return err
70
+
}
71
+
72
+
// all owners are also members
73
+
_, err = e.E.AddGroupingPolicy("server:owner", "server:member", knot)
74
+
return err
75
+
}
76
+
77
+
func (e *Enforcer) AddSpindle(spindle string) error {
78
+
// the internal repr for spindles is spindle:foo.com
79
+
spindle = intoSpindle(spindle)
80
+
81
+
_, err := e.E.AddPolicies([][]string{
82
+
{"server:owner", spindle, spindle, "server:invite"},
67
83
})
68
84
if err != nil {
69
85
return err
70
86
}
71
87
72
88
// all owners are also members
73
-
_, err = e.E.AddGroupingPolicy("server:owner", "server:member", domain)
89
+
_, err = e.E.AddGroupingPolicy("server:owner", "server:member", spindle)
74
90
return err
75
91
}
76
92
77
-
func (e *Enforcer) GetDomainsForUser(did string) ([]string, error) {
78
-
return e.E.GetDomainsForUser(did)
93
+
func (e *Enforcer) GetKnotsForUser(did string) ([]string, error) {
94
+
keepFunc := isNotSpindle
95
+
stripFunc := unSpindle
96
+
return e.getDomainsForUser(did, keepFunc, stripFunc)
79
97
}
80
98
81
-
func (e *Enforcer) AddOwner(domain, owner string) error {
82
-
_, err := e.E.AddGroupingPolicy(owner, "server:owner", domain)
83
-
return err
99
+
func (e *Enforcer) GetSpindlesForUser(did string) ([]string, error) {
100
+
keepFunc := isSpindle
101
+
stripFunc := unSpindle
102
+
return e.getDomainsForUser(did, keepFunc, stripFunc)
84
103
}
85
104
86
-
func (e *Enforcer) AddMember(domain, member string) error {
87
-
_, err := e.E.AddGroupingPolicy(member, "server:member", domain)
88
-
return err
105
+
func (e *Enforcer) AddKnotOwner(domain, owner string) error {
106
+
return e.addOwner(domain, owner)
107
+
}
108
+
109
+
func (e *Enforcer) AddKnotMember(domain, member string) error {
110
+
return e.addMember(domain, member)
111
+
}
112
+
113
+
func (e *Enforcer) AddSpindleOwner(domain, owner string) error {
114
+
return e.addOwner(intoSpindle(domain), owner)
115
+
}
116
+
117
+
func (e *Enforcer) AddSpindleMember(domain, member string) error {
118
+
return e.addMember(intoSpindle(domain), member)
89
119
}
90
120
91
121
func repoPolicies(member, domain, repo string) [][]string {
···
162
192
return nil, err
163
193
}
164
194
165
-
return membersWithoutRoles, nil
195
+
slices.Sort(membersWithoutRoles)
196
+
return slices.Compact(membersWithoutRoles), nil
166
197
}
167
198
168
-
func (e *Enforcer) isRole(user, role, domain string) (bool, error) {
169
-
return e.E.HasGroupingPolicy(user, role, domain)
199
+
func (e *Enforcer) GetUserByRoleInRepo(role, domain, repo string) ([]string, error) {
200
+
var users []string
201
+
202
+
policies, err := e.E.GetImplicitUsersForResourceByDomain(repo, domain)
203
+
for _, p := range policies {
204
+
user := p[0]
205
+
if strings.HasPrefix(user, "did:") {
206
+
users = append(users, user)
207
+
}
208
+
}
209
+
if err != nil {
210
+
return nil, err
211
+
}
212
+
213
+
slices.Sort(users)
214
+
return slices.Compact(users), nil
170
215
}
171
216
172
-
func (e *Enforcer) IsServerOwner(user, domain string) (bool, error) {
217
+
func (e *Enforcer) IsKnotOwner(user, domain string) (bool, error) {
173
218
return e.isRole(user, "server:owner", domain)
174
219
}
175
220
176
-
func (e *Enforcer) IsServerMember(user, domain string) (bool, error) {
221
+
func (e *Enforcer) IsKnotMember(user, domain string) (bool, error) {
177
222
return e.isRole(user, "server:member", domain)
178
223
}
179
224
225
+
func (e *Enforcer) IsSpindleOwner(user, domain string) (bool, error) {
226
+
return e.isRole(user, "server:owner", intoSpindle(domain))
227
+
}
228
+
229
+
func (e *Enforcer) IsSpindleMember(user, domain string) (bool, error) {
230
+
return e.isRole(user, "server:member", intoSpindle(domain))
231
+
}
232
+
233
+
func (e *Enforcer) IsKnotInviteAllowed(user, domain string) (bool, error) {
234
+
return e.isInviteAllowed(user, domain)
235
+
}
236
+
237
+
func (e *Enforcer) IsSpindleInviteAllowed(user, domain string) (bool, error) {
238
+
return e.isInviteAllowed(user, intoSpindle(domain))
239
+
}
240
+
180
241
func (e *Enforcer) IsPushAllowed(user, domain, repo string) (bool, error) {
181
242
return e.E.Enforce(user, domain, repo, "repo:push")
182
243
}
···
202
263
203
264
return permissions
204
265
}
205
-
206
-
func checkRepoFormat(repo string) error {
207
-
// sanity check, repo must be of the form ownerDid/repo
208
-
if parts := strings.SplitN(repo, "/", 2); !strings.HasPrefix(parts[0], "did:") {
209
-
return fmt.Errorf("invalid repo: %s", repo)
210
-
}
211
-
212
-
return nil
213
-
}
+83
rbac/util.go
+83
rbac/util.go
···
1
+
package rbac
2
+
3
+
import (
4
+
"fmt"
5
+
"slices"
6
+
"strings"
7
+
)
8
+
9
+
func (e *Enforcer) getDomainsForUser(did string, keepFunc func(string) bool, stripFunc func(string) string) ([]string, error) {
10
+
domains, err := e.E.GetDomainsForUser(did)
11
+
if err != nil {
12
+
return nil, err
13
+
}
14
+
15
+
n := 0
16
+
for _, x := range domains {
17
+
if keepFunc(x) {
18
+
domains[n] = stripFunc(x)
19
+
n++
20
+
}
21
+
}
22
+
domains = domains[:n]
23
+
24
+
return domains, nil
25
+
}
26
+
27
+
func (e *Enforcer) addOwner(domain, owner string) error {
28
+
_, err := e.E.AddGroupingPolicy(owner, "server:owner", domain)
29
+
return err
30
+
}
31
+
32
+
func (e *Enforcer) addMember(domain, member string) error {
33
+
_, err := e.E.AddGroupingPolicy(member, "server:member", domain)
34
+
return err
35
+
}
36
+
37
+
func (e *Enforcer) isRole(user, role, domain string) (bool, error) {
38
+
roles, err := e.E.GetImplicitRolesForUser(user, domain)
39
+
if err != nil {
40
+
return false, err
41
+
}
42
+
if slices.Contains(roles, role) {
43
+
return true, nil
44
+
}
45
+
return false, nil
46
+
}
47
+
48
+
func (e *Enforcer) isInviteAllowed(user, domain string) (bool, error) {
49
+
return e.E.Enforce(user, domain, domain, "server:invite")
50
+
}
51
+
52
+
func checkRepoFormat(repo string) error {
53
+
// sanity check, repo must be of the form ownerDid/repo
54
+
if parts := strings.SplitN(repo, "/", 2); !strings.HasPrefix(parts[0], "did:") {
55
+
return fmt.Errorf("invalid repo: %s", repo)
56
+
}
57
+
58
+
return nil
59
+
}
60
+
61
+
const spindlePrefix = "spindle:"
62
+
63
+
func intoSpindle(domain string) string {
64
+
if !isSpindle(domain) {
65
+
return spindlePrefix + domain
66
+
}
67
+
return domain
68
+
}
69
+
70
+
func unSpindle(domain string) string {
71
+
if !isSpindle(domain) {
72
+
return domain
73
+
}
74
+
return strings.TrimPrefix(domain, spindlePrefix)
75
+
}
76
+
77
+
func isSpindle(domain string) bool {
78
+
return strings.HasPrefix(domain, spindlePrefix)
79
+
}
80
+
81
+
func isNotSpindle(domain string) bool {
82
+
return !isSpindle(domain)
83
+
}