forked from tangled.org/core
Monorepo for Tangled

rbac: add some much needed tests to rbac module

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li a58af28f fc637d68

verified
Changed files
+303
rbac
+303
rbac/rbac_test.go
··· 1 + package rbac_test 2 + 3 + import ( 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 + 16 + func 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 + 34 + func 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 + 52 + func 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 + 82 + func 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 + 126 + func 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 + 154 + func 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 + 181 + func 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 + 197 + func 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 + 204 + func 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 + 217 + func 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 + 228 + func 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 + 234 + func 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 + 244 + func 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 + 259 + func 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 + 287 + func 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 + }