+1
-1
appview/oauth/handler/handler.go
+1
-1
appview/oauth/handler/handler.go
+1
-1
appview/repo/repo.go
+1
-1
appview/repo/repo.go
+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
}
337
338
// add basic acls for this domain
339
-
err = s.enforcer.AddDomain(domain)
340
if err != nil {
341
log.Println("failed to setup owner of domain", err)
342
http.Error(w, err.Error(), http.StatusInternalServerError)
···
344
}
345
346
// add this did as owner of this domain
347
-
err = s.enforcer.AddOwner(domain, reg.ByDid)
348
if err != nil {
349
log.Println("failed to setup owner of domain", err)
350
http.Error(w, err.Error(), http.StatusInternalServerError)
···
409
}
410
}
411
412
-
ok, err := s.enforcer.IsServerOwner(user.Did, domain)
413
isOwner := err == nil && ok
414
415
p := pages.KnotParams{
···
528
return
529
}
530
531
-
err = s.enforcer.AddMember(domain, subjectIdentity.DID.String())
532
if err != nil {
533
w.Write([]byte(fmt.Sprint("failed to add member: ", err)))
534
return
···
576
switch r.Method {
577
case http.MethodGet:
578
user := s.oauth.GetUser(r)
579
-
knots, err := s.enforcer.GetDomainsForUser(user.Did)
580
if err != nil {
581
s.pages.Notice(w, "repo", "Invalid user account.")
582
return
···
336
}
337
338
// add basic acls for this domain
339
+
err = s.enforcer.AddKnot(domain)
340
if err != nil {
341
log.Println("failed to setup owner of domain", err)
342
http.Error(w, err.Error(), http.StatusInternalServerError)
···
344
}
345
346
// add this did as owner of this domain
347
+
err = s.enforcer.AddKnotOwner(domain, reg.ByDid)
348
if err != nil {
349
log.Println("failed to setup owner of domain", err)
350
http.Error(w, err.Error(), http.StatusInternalServerError)
···
409
}
410
}
411
412
+
ok, err := s.enforcer.IsKnotOwner(user.Did, domain)
413
isOwner := err == nil && ok
414
415
p := pages.KnotParams{
···
528
return
529
}
530
531
+
err = s.enforcer.AddKnotMember(domain, subjectIdentity.DID.String())
532
if err != nil {
533
w.Write([]byte(fmt.Sprint("failed to add member: ", err)))
534
return
···
576
switch r.Method {
577
case http.MethodGet:
578
user := s.oauth.GetUser(r)
579
+
knots, err := s.enforcer.GetKnotsForUser(user.Did)
580
if err != nil {
581
s.pages.Notice(w, "repo", "Invalid user account.")
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
+2
-2
knotserver/routes.go
+2
-2
knotserver/routes.go
···
1177
}
1178
h.jc.AddDid(did)
1179
1180
-
if err := h.e.AddMember(ThisServer, did); err != nil {
1181
l.Error("adding member", "error", err.Error())
1182
writeError(w, err.Error(), http.StatusInternalServerError)
1183
return
···
1312
}
1313
h.jc.AddDid(data.Did)
1314
1315
-
if err := h.e.AddOwner(ThisServer, data.Did); err != nil {
1316
l.Error("adding owner", "error", err.Error())
1317
writeError(w, err.Error(), http.StatusInternalServerError)
1318
return
···
1177
}
1178
h.jc.AddDid(did)
1179
1180
+
if err := h.e.AddKnotMember(ThisServer, did); err != nil {
1181
l.Error("adding member", "error", err.Error())
1182
writeError(w, err.Error(), http.StatusInternalServerError)
1183
return
···
1312
}
1313
h.jc.AddDid(data.Did)
1314
1315
+
if err := h.e.AddKnotOwner(ThisServer, data.Did); err != nil {
1316
l.Error("adding owner", "error", err.Error())
1317
writeError(w, err.Error(), http.StatusInternalServerError)
1318
return
+79
-27
rbac/rbac.go
+79
-27
rbac/rbac.go
···
2
3
import (
4
"database/sql"
5
-
"fmt"
6
"strings"
7
8
adapter "github.com/Blank-Xu/sql-adapter"
···
59
return &Enforcer{e}, nil
60
}
61
62
-
func (e *Enforcer) AddDomain(domain string) error {
63
// Add policies with patterns
64
_, err := e.E.AddPolicies([][]string{
65
-
{"server:owner", domain, domain, "server:invite"},
66
-
{"server:member", domain, domain, "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", domain)
74
return err
75
}
76
77
-
func (e *Enforcer) GetDomainsForUser(did string) ([]string, error) {
78
-
return e.E.GetDomainsForUser(did)
79
}
80
81
-
func (e *Enforcer) AddOwner(domain, owner string) error {
82
-
_, err := e.E.AddGroupingPolicy(owner, "server:owner", domain)
83
-
return err
84
}
85
86
-
func (e *Enforcer) AddMember(domain, member string) error {
87
-
_, err := e.E.AddGroupingPolicy(member, "server:member", domain)
88
-
return err
89
}
90
91
func repoPolicies(member, domain, repo string) [][]string {
···
162
return nil, err
163
}
164
165
-
return membersWithoutRoles, nil
166
}
167
168
-
func (e *Enforcer) isRole(user, role, domain string) (bool, error) {
169
-
return e.E.HasGroupingPolicy(user, role, domain)
170
}
171
172
-
func (e *Enforcer) IsServerOwner(user, domain string) (bool, error) {
173
return e.isRole(user, "server:owner", domain)
174
}
175
176
-
func (e *Enforcer) IsServerMember(user, domain string) (bool, error) {
177
return e.isRole(user, "server:member", domain)
178
}
179
180
func (e *Enforcer) IsPushAllowed(user, domain, repo string) (bool, error) {
181
return e.E.Enforce(user, domain, repo, "repo:push")
182
}
···
202
203
return permissions
204
}
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
-
}
···
2
3
import (
4
"database/sql"
5
+
"slices"
6
"strings"
7
8
adapter "github.com/Blank-Xu/sql-adapter"
···
59
return &Enforcer{e}, nil
60
}
61
62
+
func (e *Enforcer) AddKnot(knot string) error {
63
// Add policies with patterns
64
_, err := e.E.AddPolicies([][]string{
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"},
83
})
84
if err != nil {
85
return err
86
}
87
88
// all owners are also members
89
+
_, err = e.E.AddGroupingPolicy("server:owner", "server:member", spindle)
90
return err
91
}
92
93
+
func (e *Enforcer) GetKnotsForUser(did string) ([]string, error) {
94
+
keepFunc := isNotSpindle
95
+
stripFunc := unSpindle
96
+
return e.getDomainsForUser(did, keepFunc, stripFunc)
97
}
98
99
+
func (e *Enforcer) GetSpindlesForUser(did string) ([]string, error) {
100
+
keepFunc := isSpindle
101
+
stripFunc := unSpindle
102
+
return e.getDomainsForUser(did, keepFunc, stripFunc)
103
}
104
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)
119
}
120
121
func repoPolicies(member, domain, repo string) [][]string {
···
192
return nil, err
193
}
194
195
+
slices.Sort(membersWithoutRoles)
196
+
return slices.Compact(membersWithoutRoles), nil
197
}
198
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
215
}
216
217
+
func (e *Enforcer) IsKnotOwner(user, domain string) (bool, error) {
218
return e.isRole(user, "server:owner", domain)
219
}
220
221
+
func (e *Enforcer) IsKnotMember(user, domain string) (bool, error) {
222
return e.isRole(user, "server:member", domain)
223
}
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
+
241
func (e *Enforcer) IsPushAllowed(user, domain, repo string) (bool, error) {
242
return e.E.Enforce(user, domain, repo, "repo:push")
243
}
···
263
264
return permissions
265
}
+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
+
}