Monorepo for Tangled
tangled.org
1package rbac
2
3import (
4 "fmt"
5 "slices"
6 "strings"
7)
8
9func (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
27func (e *Enforcer) addOwner(domain, owner string) error {
28 _, err := e.E.AddGroupingPolicy(owner, "server:owner", domain)
29 return err
30}
31
32func (e *Enforcer) removeOwner(domain, owner string) error {
33 _, err := e.E.RemoveGroupingPolicy(owner, "server:owner", domain)
34 return err
35}
36
37func (e *Enforcer) addMember(domain, member string) (bool, error) {
38 return e.E.AddGroupingPolicy(member, "server:member", domain)
39}
40
41func (e *Enforcer) removeMember(domain, member string) (bool, error) {
42 return e.E.RemoveGroupingPolicy(member, "server:member", domain)
43}
44
45func (e *Enforcer) isRole(user, role, domain string) (bool, error) {
46 roles, err := e.E.GetImplicitRolesForUser(user, domain)
47 if err != nil {
48 return false, err
49 }
50 if slices.Contains(roles, role) {
51 return true, nil
52 }
53 return false, nil
54}
55
56func (e *Enforcer) isInviteAllowed(user, domain string) (bool, error) {
57 return e.E.Enforce(user, domain, domain, "server:invite")
58}
59
60func (e *Enforcer) HasAnyPolicyForUser(user string) (bool, error) {
61 pPolicies, err := e.E.GetFilteredNamedPolicy("p", 0, user)
62 if err != nil {
63 return false, err
64 }
65 if len(pPolicies) > 0 {
66 return true, nil
67 }
68 gPolicies, err := e.E.GetFilteredNamedGroupingPolicy("g", 0, user)
69 if err != nil {
70 return false, err
71 }
72 return len(gPolicies) > 0, nil
73}
74
75func (e *Enforcer) wouldHaveAnyPolicyExcludingGrouping(user, role, domain string) (bool, error) {
76 pPolicies, err := e.E.GetFilteredNamedPolicy("p", 0, user)
77 if err != nil {
78 return false, err
79 }
80 if len(pPolicies) > 0 {
81 return true, nil
82 }
83 gPolicies, err := e.E.GetFilteredNamedGroupingPolicy("g", 0, user)
84 if err != nil {
85 return false, err
86 }
87 for _, gp := range gPolicies {
88 if len(gp) < 3 {
89 return true, nil
90 }
91 if gp[1] != role || gp[2] != domain {
92 return true, nil
93 }
94 }
95 return false, nil
96}
97
98func (e *Enforcer) WouldHaveAnyPolicyExcludingKnotMember(user, domain string) (bool, error) {
99 return e.wouldHaveAnyPolicyExcludingGrouping(user, "server:member", domain)
100}
101
102func (e *Enforcer) WouldHaveAnyPolicyExcludingSpindleMember(user, domain string) (bool, error) {
103 return e.wouldHaveAnyPolicyExcludingGrouping(user, "server:member", intoSpindle(domain))
104}
105
106func checkRepoFormat(repo string) error {
107 // sanity check, repo must be of the form ownerDid/repo
108 if parts := strings.SplitN(repo, "/", 2); !strings.HasPrefix(parts[0], "did:") {
109 return fmt.Errorf("invalid repo: %s", repo)
110 }
111
112 return nil
113}
114
115const spindlePrefix = "spindle:"
116
117func intoSpindle(domain string) string {
118 if !isSpindle(domain) {
119 return spindlePrefix + domain
120 }
121 return domain
122}
123
124func unSpindle(domain string) string {
125 if !isSpindle(domain) {
126 return domain
127 }
128 return strings.TrimPrefix(domain, spindlePrefix)
129}
130
131func isSpindle(domain string) bool {
132 return strings.HasPrefix(domain, spindlePrefix)
133}
134
135func isNotSpindle(domain string) bool {
136 return !isSpindle(domain)
137}