this repo has no description
1package rbac 2 3import ( 4 "database/sql" 5 "path" 6 "strings" 7 8 sqladapter "github.com/Blank-Xu/sql-adapter" 9 "github.com/casbin/casbin/v2" 10 "github.com/casbin/casbin/v2/model" 11) 12 13const ( 14 Model = ` 15[request_definition] 16r = sub, dom, obj, act 17 18[policy_definition] 19p = sub, dom, obj, act 20 21[role_definition] 22g = _, _, _ 23 24[policy_effect] 25e = some(where (p.eft == allow)) 26 27[matchers] 28m = r.act == p.act && r.dom == p.dom && keyMatch2(r.obj, p.obj) && g(r.sub, p.sub, r.dom) 29` 30) 31 32type Enforcer struct { 33 E *casbin.SyncedEnforcer 34} 35 36func keyMatch2(key1 string, key2 string) bool { 37 matched, _ := path.Match(key2, key1) 38 return matched 39} 40 41func NewEnforcer(path string) (*Enforcer, error) { 42 m, err := model.NewModelFromString(Model) 43 if err != nil { 44 return nil, err 45 } 46 47 db, err := sql.Open("sqlite3", path) 48 if err != nil { 49 return nil, err 50 } 51 52 a, err := sqladapter.NewAdapter(db, "sqlite3", "acl") 53 if err != nil { 54 return nil, err 55 } 56 57 e, err := casbin.NewSyncedEnforcer(m, a) 58 if err != nil { 59 return nil, err 60 } 61 62 e.EnableAutoSave(true) 63 e.AddFunction("keyMatch2", keyMatch2Func) 64 65 return &Enforcer{e}, nil 66} 67 68func (e *Enforcer) AddDomain(domain string) error { 69 // Add policies with patterns 70 _, err := e.E.AddPolicies([][]string{ 71 {"server:owner", domain, domain, "server:invite"}, 72 {"server:member", domain, domain, "repo:create"}, 73 }) 74 if err != nil { 75 return err 76 } 77 78 // all owners are also members 79 _, err = e.E.AddGroupingPolicy("server:owner", "server:member", domain) 80 return err 81} 82 83func (e *Enforcer) GetDomainsForUser(did string) ([]string, error) { 84 return e.E.Enforcer.GetDomainsForUser(did) 85} 86 87func (e *Enforcer) AddOwner(domain, owner string) error { 88 _, err := e.E.AddGroupingPolicy(owner, "server:owner", domain) 89 return err 90} 91 92func (e *Enforcer) AddMember(domain, member string) error { 93 _, err := e.E.AddGroupingPolicy(member, "server:member", domain) 94 return err 95} 96 97func (e *Enforcer) AddRepo(member, domain, repo string) error { 98 _, err := e.E.AddPolicies([][]string{ 99 {member, domain, repo, "repo:push"}, 100 {member, domain, repo, "repo:owner"}, 101 {member, domain, repo, "repo:invite"}, 102 {member, domain, repo, "repo:delete"}, 103 {"server:owner", domain, repo, "repo:delete"}, // server owner can delete any repo 104 }) 105 return err 106} 107 108func (e *Enforcer) GetUserByRole(role, domain string) ([]string, error) { 109 var membersWithoutRoles []string 110 111 // this includes roles too, casbin does not differentiate. 112 // the filtering criteria is to remove strings not starting with `did:` 113 members, err := e.E.Enforcer.GetImplicitUsersForRole(role, domain) 114 for _, m := range members { 115 if strings.HasPrefix(m, "did:") { 116 membersWithoutRoles = append(membersWithoutRoles, m) 117 } 118 } 119 if err != nil { 120 return nil, err 121 } 122 123 return membersWithoutRoles, nil 124} 125 126func (e *Enforcer) isRole(user, role, domain string) (bool, error) { 127 return e.E.HasGroupingPolicy(user, role, domain) 128} 129 130func (e *Enforcer) IsServerOwner(user, domain string) (bool, error) { 131 return e.isRole(user, "server:owner", domain) 132} 133 134func (e *Enforcer) IsServerMember(user, domain string) (bool, error) { 135 return e.isRole(user, "server:member", domain) 136} 137 138func (e *Enforcer) IsPushAllowed(user, domain, repo string) (bool, error) { 139 return e.E.Enforce(user, domain, repo, "repo:push") 140} 141 142// keyMatch2Func is a wrapper for keyMatch2 to make it compatible with Casbin 143func keyMatch2Func(args ...interface{}) (interface{}, error) { 144 name1 := args[0].(string) 145 name2 := args[1].(string) 146 147 return keyMatch2(name1, name2), nil 148}