forked from tangled.org/core
this repo has no description
1package rbac_test 2 3import ( 4 "database/sql" 5 "testing" 6 7 "tangled.sh/tangled.sh/core/rbac" 8 9 adapter "github.com/Blank-Xu/sql-adapter" 10 "github.com/casbin/casbin/v2" 11 "github.com/casbin/casbin/v2/model" 12 _ "github.com/mattn/go-sqlite3" 13 "github.com/stretchr/testify/assert" 14) 15 16func setup(t *testing.T) *rbac.Enforcer { 17 db, err := sql.Open("sqlite3", ":memory:") 18 assert.NoError(t, err) 19 20 a, err := adapter.NewAdapter(db, "sqlite3", "acl") 21 assert.NoError(t, err) 22 23 m, err := model.NewModelFromString(rbac.Model) 24 assert.NoError(t, err) 25 26 e, err := casbin.NewEnforcer(m, a) 27 assert.NoError(t, err) 28 29 e.EnableAutoSave(false) 30 31 return &rbac.Enforcer{E: e} 32} 33 34func TestAddKnotAndRoles(t *testing.T) { 35 e := setup(t) 36 37 err := e.AddKnot("example.com") 38 assert.NoError(t, err) 39 40 err = e.AddKnotOwner("example.com", "did:plc:foo") 41 assert.NoError(t, err) 42 43 isOwner, err := e.IsKnotOwner("did:plc:foo", "example.com") 44 assert.NoError(t, err) 45 assert.True(t, isOwner) 46 47 isMember, err := e.IsKnotMember("did:plc:foo", "example.com") 48 assert.NoError(t, err) 49 assert.True(t, isMember) 50} 51 52func TestAddMember(t *testing.T) { 53 e := setup(t) 54 55 err := e.AddKnot("example.com") 56 assert.NoError(t, err) 57 58 err = e.AddKnotOwner("example.com", "did:plc:foo") 59 assert.NoError(t, err) 60 61 err = e.AddKnotMember("example.com", "did:plc:bar") 62 assert.NoError(t, err) 63 64 isMember, err := e.IsKnotMember("did:plc:foo", "example.com") 65 assert.NoError(t, err) 66 assert.True(t, isMember) 67 68 isMember, err = e.IsKnotMember("did:plc:bar", "example.com") 69 assert.NoError(t, err) 70 assert.True(t, isMember) 71 72 isOwner, err := e.IsKnotOwner("did:plc:foo", "example.com") 73 assert.NoError(t, err) 74 assert.True(t, isOwner) 75 76 // negated check here 77 isOwner, err = e.IsKnotOwner("did:plc:bar", "example.com") 78 assert.NoError(t, err) 79 assert.False(t, isOwner) 80} 81 82func TestAddRepoPermissions(t *testing.T) { 83 e := setup(t) 84 85 knot := "example.com" 86 87 fooUser := "did:plc:foo" 88 fooRepo := "did:plc:foo/my-repo" 89 90 barUser := "did:plc:bar" 91 barRepo := "did:plc:bar/my-repo" 92 93 _ = e.AddKnot(knot) 94 _ = e.AddKnotMember(knot, fooUser) 95 _ = e.AddKnotMember(knot, barUser) 96 97 err := e.AddRepo(fooUser, knot, fooRepo) 98 assert.NoError(t, err) 99 100 err = e.AddRepo(barUser, knot, barRepo) 101 assert.NoError(t, err) 102 103 canPush, err := e.IsPushAllowed(fooUser, knot, fooRepo) 104 assert.NoError(t, err) 105 assert.True(t, canPush) 106 107 canPush, err = e.IsPushAllowed(barUser, knot, barRepo) 108 assert.NoError(t, err) 109 assert.True(t, canPush) 110 111 // negated 112 canPush, err = e.IsPushAllowed(barUser, knot, fooRepo) 113 assert.NoError(t, err) 114 assert.False(t, canPush) 115 116 canDelete, err := e.E.Enforce(fooUser, knot, fooRepo, "repo:delete") 117 assert.NoError(t, err) 118 assert.True(t, canDelete) 119 120 // negated 121 canDelete, err = e.E.Enforce(barUser, knot, fooRepo, "repo:delete") 122 assert.NoError(t, err) 123 assert.False(t, canDelete) 124} 125 126func TestCollaboratorPermissions(t *testing.T) { 127 e := setup(t) 128 129 knot := "example.com" 130 repo := "did:plc:foo/my-repo" 131 owner := "did:plc:foo" 132 collaborator := "did:plc:bar" 133 134 _ = e.AddKnot(knot) 135 _ = e.AddRepo(owner, knot, repo) 136 137 err := e.AddCollaborator(collaborator, knot, repo) 138 assert.NoError(t, err) 139 140 // all collaborator permissions granted 141 perms := e.GetPermissionsInRepo(collaborator, knot, repo) 142 assert.ElementsMatch(t, []string{ 143 "repo:settings", "repo:push", "repo:collaborator", 144 }, perms) 145 146 err = e.RemoveCollaborator(collaborator, knot, repo) 147 assert.NoError(t, err) 148 149 // all permissions removed 150 perms = e.GetPermissionsInRepo(collaborator, knot, repo) 151 assert.ElementsMatch(t, []string{}, perms) 152} 153 154func TestGetByRole(t *testing.T) { 155 e := setup(t) 156 157 knot := "example.com" 158 repo := "did:plc:foo/my-repo" 159 owner := "did:plc:foo" 160 collaborator1 := "did:plc:bar" 161 collaborator2 := "did:plc:baz" 162 163 _ = e.AddKnot(knot) 164 _ = e.AddRepo(owner, knot, repo) 165 166 err := e.AddCollaborator(collaborator1, knot, repo) 167 assert.NoError(t, err) 168 169 err = e.AddCollaborator(collaborator2, knot, repo) 170 assert.NoError(t, err) 171 172 collaborators, err := e.GetUserByRoleInRepo("repo:collaborator", knot, repo) 173 assert.NoError(t, err) 174 assert.ElementsMatch(t, []string{ 175 "did:plc:foo", // owner 176 "did:plc:bar", // collaborator1 177 "did:plc:baz", // collaborator2 178 }, collaborators) 179} 180 181func TestGetPermissionsInRepo(t *testing.T) { 182 e := setup(t) 183 184 user := "did:plc:foo" 185 knot := "example.com" 186 repo := "did:plc:foo/my-repo" 187 188 _ = e.AddKnot(knot) 189 _ = e.AddRepo(user, knot, repo) 190 191 perms := e.GetPermissionsInRepo(user, knot, repo) 192 assert.ElementsMatch(t, []string{ 193 "repo:settings", "repo:push", "repo:owner", "repo:invite", "repo:delete", 194 }, perms) 195} 196 197func TestInvalidRepoFormat(t *testing.T) { 198 e := setup(t) 199 200 err := e.AddRepo("did:plc:foo", "example.com", "not-valid-format") 201 assert.Error(t, err) 202} 203 204func TestGetKnotssForUser(t *testing.T) { 205 e := setup(t) 206 _ = e.AddKnot("example.com") 207 _ = e.AddKnotOwner("example.com", "did:plc:foo") 208 _ = e.AddKnotMember("example.com", "did:plc:bar") 209 210 knots1, _ := e.GetKnotsForUser("did:plc:foo") 211 assert.Contains(t, knots1, "example.com") 212 213 knots2, _ := e.GetKnotsForUser("did:plc:bar") 214 assert.Contains(t, knots2, "example.com") 215} 216 217func TestGetUserByRole(t *testing.T) { 218 e := setup(t) 219 _ = e.AddKnot("example.com") 220 _ = e.AddKnotMember("example.com", "did:plc:foo") 221 _ = e.AddKnotOwner("example.com", "did:plc:bar") 222 223 members, _ := e.GetUserByRole("server:member", "example.com") 224 assert.Contains(t, members, "did:plc:foo") 225 assert.Contains(t, members, "did:plc:bar") // due to inheritance 226} 227 228func TestEmptyUserPermissions(t *testing.T) { 229 e := setup(t) 230 allowed, _ := e.IsPushAllowed("did:plc:nobody", "unknown.com", "did:plc:nobody/repo") 231 assert.False(t, allowed) 232} 233 234func TestDuplicatePolicyAddition(t *testing.T) { 235 e := setup(t) 236 _ = e.AddKnot("example.com") 237 _ = e.AddRepo("did:plc:foo", "example.com", "did:plc:foo/repo") 238 239 // add again 240 err := e.AddRepo("did:plc:foo", "example.com", "did:plc:foo/repo") 241 assert.NoError(t, err) // should not fail, but won't duplicate 242} 243 244func TestRemoveRepo(t *testing.T) { 245 e := setup(t) 246 repo := "did:plc:foo/repo" 247 _ = e.AddKnot("example.com") 248 _ = e.AddRepo("did:plc:foo", "example.com", repo) 249 250 allowed, _ := e.IsSettingsAllowed("did:plc:foo", "example.com", repo) 251 assert.True(t, allowed) 252 253 _ = e.RemoveRepo("did:plc:foo", "example.com", repo) 254 255 allowed, _ = e.IsSettingsAllowed("did:plc:foo", "example.com", repo) 256 assert.False(t, allowed) 257} 258 259func TestAddKnotAndSpindle(t *testing.T) { 260 e := setup(t) 261 262 err := e.AddKnot("k.com") 263 assert.NoError(t, err) 264 265 err = e.AddSpindle("s.com") 266 assert.NoError(t, err) 267 268 err = e.AddKnotOwner("k.com", "did:plc:foo") 269 assert.NoError(t, err) 270 271 err = e.AddSpindleOwner("s.com", "did:plc:foo") 272 assert.NoError(t, err) 273 274 knots, err := e.GetKnotsForUser("did:plc:foo") 275 assert.NoError(t, err) 276 assert.ElementsMatch(t, []string{ 277 "k.com", 278 }, knots) 279 280 spindles, err := e.GetSpindlesForUser("did:plc:foo") 281 assert.NoError(t, err) 282 assert.ElementsMatch(t, []string{ 283 "s.com", 284 }, spindles) 285} 286 287func TestAddSpindleAndRoles(t *testing.T) { 288 e := setup(t) 289 290 err := e.AddSpindle("s.com") 291 assert.NoError(t, err) 292 293 err = e.AddSpindleOwner("s.com", "did:plc:foo") 294 assert.NoError(t, err) 295 296 ok, err := e.IsSpindleOwner("did:plc:foo", "s.com") 297 assert.NoError(t, err) 298 assert.True(t, ok) 299 300 ok, err = e.IsSpindleMember("did:plc:foo", "s.com") 301 assert.NoError(t, err) 302 assert.True(t, ok) 303}