forked from tangled.org/core
this repo has no description
at master 11 kB view raw
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:?_foreign_keys=1") 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 TestGetKnotUsersByRole(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.GetKnotUsersByRole("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 TestGetSpindleUsersByRole(t *testing.T) { 229 e := setup(t) 230 _ = e.AddSpindle("example.com") 231 _ = e.AddSpindleMember("example.com", "did:plc:foo") 232 _ = e.AddSpindleOwner("example.com", "did:plc:bar") 233 234 members, _ := e.GetSpindleUsersByRole("server:member", "example.com") 235 assert.Contains(t, members, "did:plc:foo") 236 assert.Contains(t, members, "did:plc:bar") // due to inheritance 237} 238 239func TestEmptyUserPermissions(t *testing.T) { 240 e := setup(t) 241 allowed, _ := e.IsPushAllowed("did:plc:nobody", "unknown.com", "did:plc:nobody/repo") 242 assert.False(t, allowed) 243} 244 245func TestDuplicatePolicyAddition(t *testing.T) { 246 e := setup(t) 247 _ = e.AddKnot("example.com") 248 _ = e.AddRepo("did:plc:foo", "example.com", "did:plc:foo/repo") 249 250 // add again 251 err := e.AddRepo("did:plc:foo", "example.com", "did:plc:foo/repo") 252 assert.NoError(t, err) // should not fail, but won't duplicate 253} 254 255func TestRemoveRepo(t *testing.T) { 256 e := setup(t) 257 repo := "did:plc:foo/repo" 258 _ = e.AddKnot("example.com") 259 _ = e.AddRepo("did:plc:foo", "example.com", repo) 260 261 allowed, _ := e.IsSettingsAllowed("did:plc:foo", "example.com", repo) 262 assert.True(t, allowed) 263 264 _ = e.RemoveRepo("did:plc:foo", "example.com", repo) 265 266 allowed, _ = e.IsSettingsAllowed("did:plc:foo", "example.com", repo) 267 assert.False(t, allowed) 268} 269 270func TestAddKnotAndSpindle(t *testing.T) { 271 e := setup(t) 272 273 err := e.AddKnot("k.com") 274 assert.NoError(t, err) 275 276 err = e.AddSpindle("s.com") 277 assert.NoError(t, err) 278 279 err = e.AddKnotOwner("k.com", "did:plc:foo") 280 assert.NoError(t, err) 281 282 err = e.AddSpindleOwner("s.com", "did:plc:foo") 283 assert.NoError(t, err) 284 285 knots, err := e.GetKnotsForUser("did:plc:foo") 286 assert.NoError(t, err) 287 assert.ElementsMatch(t, []string{ 288 "k.com", 289 }, knots) 290 291 spindles, err := e.GetSpindlesForUser("did:plc:foo") 292 assert.NoError(t, err) 293 assert.ElementsMatch(t, []string{ 294 "s.com", 295 }, spindles) 296} 297 298func TestAddSpindleAndRoles(t *testing.T) { 299 e := setup(t) 300 301 err := e.AddSpindle("s.com") 302 assert.NoError(t, err) 303 304 err = e.AddSpindleOwner("s.com", "did:plc:foo") 305 assert.NoError(t, err) 306 307 ok, err := e.IsSpindleOwner("did:plc:foo", "s.com") 308 assert.NoError(t, err) 309 assert.True(t, ok) 310 311 ok, err = e.IsSpindleMember("did:plc:foo", "s.com") 312 assert.NoError(t, err) 313 assert.True(t, ok) 314} 315 316func TestRemoveKnotOwner(t *testing.T) { 317 e := setup(t) 318 319 err := e.AddKnot("k.com") 320 assert.NoError(t, err) 321 322 err = e.AddKnotOwner("k.com", "did:plc:foo") 323 assert.NoError(t, err) 324 325 knots, err := e.GetKnotsForUser("did:plc:foo") 326 assert.NoError(t, err) 327 assert.ElementsMatch(t, []string{ 328 "k.com", 329 }, knots) 330 331 err = e.RemoveKnotOwner("k.com", "did:plc:foo") 332 assert.NoError(t, err) 333 334 knots, err = e.GetKnotsForUser("did:plc:foo") 335 assert.NoError(t, err) 336 assert.Empty(t, knots) 337} 338 339func TestRemoveKnotMember(t *testing.T) { 340 e := setup(t) 341 342 err := e.AddKnot("k.com") 343 assert.NoError(t, err) 344 345 err = e.AddKnotOwner("k.com", "did:plc:foo") 346 assert.NoError(t, err) 347 348 err = e.AddKnotMember("k.com", "did:plc:bar") 349 assert.NoError(t, err) 350 351 knots, err := e.GetKnotsForUser("did:plc:bar") 352 assert.NoError(t, err) 353 assert.ElementsMatch(t, []string{ 354 "k.com", 355 }, knots) 356 357 err = e.RemoveKnotMember("k.com", "did:plc:bar") 358 assert.NoError(t, err) 359 360 knots, err = e.GetKnotsForUser("did:plc:bar") 361 assert.NoError(t, err) 362 assert.Empty(t, knots) 363} 364 365func TestRemoveSpindleOwner(t *testing.T) { 366 e := setup(t) 367 368 err := e.AddSpindle("s.com") 369 assert.NoError(t, err) 370 371 err = e.AddSpindleOwner("s.com", "did:plc:foo") 372 assert.NoError(t, err) 373 374 spindles, err := e.GetSpindlesForUser("did:plc:foo") 375 assert.NoError(t, err) 376 assert.ElementsMatch(t, []string{ 377 "s.com", 378 }, spindles) 379 380 err = e.RemoveSpindleOwner("s.com", "did:plc:foo") 381 assert.NoError(t, err) 382 383 spindles, err = e.GetSpindlesForUser("did:plc:foo") 384 assert.NoError(t, err) 385 assert.Empty(t, spindles) 386} 387 388func TestRemoveSpindleMember(t *testing.T) { 389 e := setup(t) 390 391 err := e.AddSpindle("s.com") 392 assert.NoError(t, err) 393 394 err = e.AddSpindleOwner("s.com", "did:plc:foo") 395 assert.NoError(t, err) 396 397 err = e.AddSpindleMember("s.com", "did:plc:bar") 398 assert.NoError(t, err) 399 400 spindles, err := e.GetSpindlesForUser("did:plc:foo") 401 assert.NoError(t, err) 402 assert.ElementsMatch(t, []string{ 403 "s.com", 404 }, spindles) 405 406 spindles, err = e.GetSpindlesForUser("did:plc:bar") 407 assert.NoError(t, err) 408 assert.ElementsMatch(t, []string{ 409 "s.com", 410 }, spindles) 411 412 err = e.RemoveSpindleMember("s.com", "did:plc:bar") 413 assert.NoError(t, err) 414 415 spindles, err = e.GetSpindlesForUser("did:plc:bar") 416 assert.NoError(t, err) 417 assert.Empty(t, spindles) 418} 419 420func TestRemoveSpindle(t *testing.T) { 421 e := setup(t) 422 423 err := e.AddSpindle("s.com") 424 assert.NoError(t, err) 425 426 err = e.AddSpindleOwner("s.com", "did:plc:foo") 427 assert.NoError(t, err) 428 429 err = e.AddSpindleMember("s.com", "did:plc:bar") 430 assert.NoError(t, err) 431 432 users, err := e.GetSpindleUsersByRole("server:member", "s.com") 433 assert.NoError(t, err) 434 assert.ElementsMatch(t, []string{ 435 "did:plc:foo", 436 "did:plc:bar", 437 }, users) 438 439 err = e.RemoveSpindle("s.com") 440 assert.NoError(t, err) 441 442 // TODO: see this issue https://github.com/casbin/casbin/issues/1492 443 // s, err := e.E.GetAllDomains() 444 // assert.Empty(t, s) 445 446 spindles, err := e.GetSpindleUsersByRole("server:member", "s.com") 447 assert.NoError(t, err) 448 assert.Empty(t, spindles) 449}