···
7
+
"tangled.sh/tangled.sh/core/rbac"
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"
16
+
func setup(t *testing.T) *rbac.Enforcer {
17
+
db, err := sql.Open("sqlite3", ":memory:")
18
+
assert.NoError(t, err)
20
+
a, err := adapter.NewAdapter(db, "sqlite3", "acl")
21
+
assert.NoError(t, err)
23
+
m, err := model.NewModelFromString(rbac.Model)
24
+
assert.NoError(t, err)
26
+
e, err := casbin.NewEnforcer(m, a)
27
+
assert.NoError(t, err)
29
+
e.EnableAutoSave(false)
31
+
return &rbac.Enforcer{E: e}
34
+
func TestAddKnotAndRoles(t *testing.T) {
37
+
err := e.AddKnot("example.com")
38
+
assert.NoError(t, err)
40
+
err = e.AddKnotOwner("example.com", "did:plc:foo")
41
+
assert.NoError(t, err)
43
+
isOwner, err := e.IsKnotOwner("did:plc:foo", "example.com")
44
+
assert.NoError(t, err)
45
+
assert.True(t, isOwner)
47
+
isMember, err := e.IsKnotMember("did:plc:foo", "example.com")
48
+
assert.NoError(t, err)
49
+
assert.True(t, isMember)
52
+
func TestAddMember(t *testing.T) {
55
+
err := e.AddKnot("example.com")
56
+
assert.NoError(t, err)
58
+
err = e.AddKnotOwner("example.com", "did:plc:foo")
59
+
assert.NoError(t, err)
61
+
err = e.AddKnotMember("example.com", "did:plc:bar")
62
+
assert.NoError(t, err)
64
+
isMember, err := e.IsKnotMember("did:plc:foo", "example.com")
65
+
assert.NoError(t, err)
66
+
assert.True(t, isMember)
68
+
isMember, err = e.IsKnotMember("did:plc:bar", "example.com")
69
+
assert.NoError(t, err)
70
+
assert.True(t, isMember)
72
+
isOwner, err := e.IsKnotOwner("did:plc:foo", "example.com")
73
+
assert.NoError(t, err)
74
+
assert.True(t, isOwner)
76
+
// negated check here
77
+
isOwner, err = e.IsKnotOwner("did:plc:bar", "example.com")
78
+
assert.NoError(t, err)
79
+
assert.False(t, isOwner)
82
+
func TestAddRepoPermissions(t *testing.T) {
85
+
knot := "example.com"
87
+
fooUser := "did:plc:foo"
88
+
fooRepo := "did:plc:foo/my-repo"
90
+
barUser := "did:plc:bar"
91
+
barRepo := "did:plc:bar/my-repo"
94
+
_ = e.AddKnotMember(knot, fooUser)
95
+
_ = e.AddKnotMember(knot, barUser)
97
+
err := e.AddRepo(fooUser, knot, fooRepo)
98
+
assert.NoError(t, err)
100
+
err = e.AddRepo(barUser, knot, barRepo)
101
+
assert.NoError(t, err)
103
+
canPush, err := e.IsPushAllowed(fooUser, knot, fooRepo)
104
+
assert.NoError(t, err)
105
+
assert.True(t, canPush)
107
+
canPush, err = e.IsPushAllowed(barUser, knot, barRepo)
108
+
assert.NoError(t, err)
109
+
assert.True(t, canPush)
112
+
canPush, err = e.IsPushAllowed(barUser, knot, fooRepo)
113
+
assert.NoError(t, err)
114
+
assert.False(t, canPush)
116
+
canDelete, err := e.E.Enforce(fooUser, knot, fooRepo, "repo:delete")
117
+
assert.NoError(t, err)
118
+
assert.True(t, canDelete)
121
+
canDelete, err = e.E.Enforce(barUser, knot, fooRepo, "repo:delete")
122
+
assert.NoError(t, err)
123
+
assert.False(t, canDelete)
126
+
func TestCollaboratorPermissions(t *testing.T) {
129
+
knot := "example.com"
130
+
repo := "did:plc:foo/my-repo"
131
+
owner := "did:plc:foo"
132
+
collaborator := "did:plc:bar"
134
+
_ = e.AddKnot(knot)
135
+
_ = e.AddRepo(owner, knot, repo)
137
+
err := e.AddCollaborator(collaborator, knot, repo)
138
+
assert.NoError(t, err)
140
+
// all collaborator permissions granted
141
+
perms := e.GetPermissionsInRepo(collaborator, knot, repo)
142
+
assert.ElementsMatch(t, []string{
143
+
"repo:settings", "repo:push", "repo:collaborator",
146
+
err = e.RemoveCollaborator(collaborator, knot, repo)
147
+
assert.NoError(t, err)
149
+
// all permissions removed
150
+
perms = e.GetPermissionsInRepo(collaborator, knot, repo)
151
+
assert.ElementsMatch(t, []string{}, perms)
154
+
func TestGetByRole(t *testing.T) {
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"
163
+
_ = e.AddKnot(knot)
164
+
_ = e.AddRepo(owner, knot, repo)
166
+
err := e.AddCollaborator(collaborator1, knot, repo)
167
+
assert.NoError(t, err)
169
+
err = e.AddCollaborator(collaborator2, knot, repo)
170
+
assert.NoError(t, err)
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
181
+
func TestGetPermissionsInRepo(t *testing.T) {
184
+
user := "did:plc:foo"
185
+
knot := "example.com"
186
+
repo := "did:plc:foo/my-repo"
188
+
_ = e.AddKnot(knot)
189
+
_ = e.AddRepo(user, knot, repo)
191
+
perms := e.GetPermissionsInRepo(user, knot, repo)
192
+
assert.ElementsMatch(t, []string{
193
+
"repo:settings", "repo:push", "repo:owner", "repo:invite", "repo:delete",
197
+
func TestInvalidRepoFormat(t *testing.T) {
200
+
err := e.AddRepo("did:plc:foo", "example.com", "not-valid-format")
201
+
assert.Error(t, err)
204
+
func TestGetKnotssForUser(t *testing.T) {
206
+
_ = e.AddKnot("example.com")
207
+
_ = e.AddKnotOwner("example.com", "did:plc:foo")
208
+
_ = e.AddKnotMember("example.com", "did:plc:bar")
210
+
knots1, _ := e.GetKnotsForUser("did:plc:foo")
211
+
assert.Contains(t, knots1, "example.com")
213
+
knots2, _ := e.GetKnotsForUser("did:plc:bar")
214
+
assert.Contains(t, knots2, "example.com")
217
+
func TestGetUserByRole(t *testing.T) {
219
+
_ = e.AddKnot("example.com")
220
+
_ = e.AddKnotMember("example.com", "did:plc:foo")
221
+
_ = e.AddKnotOwner("example.com", "did:plc:bar")
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
228
+
func TestEmptyUserPermissions(t *testing.T) {
230
+
allowed, _ := e.IsPushAllowed("did:plc:nobody", "unknown.com", "did:plc:nobody/repo")
231
+
assert.False(t, allowed)
234
+
func TestDuplicatePolicyAddition(t *testing.T) {
236
+
_ = e.AddKnot("example.com")
237
+
_ = e.AddRepo("did:plc:foo", "example.com", "did:plc:foo/repo")
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
244
+
func TestRemoveRepo(t *testing.T) {
246
+
repo := "did:plc:foo/repo"
247
+
_ = e.AddKnot("example.com")
248
+
_ = e.AddRepo("did:plc:foo", "example.com", repo)
250
+
allowed, _ := e.IsSettingsAllowed("did:plc:foo", "example.com", repo)
251
+
assert.True(t, allowed)
253
+
_ = e.RemoveRepo("did:plc:foo", "example.com", repo)
255
+
allowed, _ = e.IsSettingsAllowed("did:plc:foo", "example.com", repo)
256
+
assert.False(t, allowed)
259
+
func TestAddKnotAndSpindle(t *testing.T) {
262
+
err := e.AddKnot("k.com")
263
+
assert.NoError(t, err)
265
+
err = e.AddSpindle("s.com")
266
+
assert.NoError(t, err)
268
+
err = e.AddKnotOwner("k.com", "did:plc:foo")
269
+
assert.NoError(t, err)
271
+
err = e.AddSpindleOwner("s.com", "did:plc:foo")
272
+
assert.NoError(t, err)
274
+
knots, err := e.GetKnotsForUser("did:plc:foo")
275
+
assert.NoError(t, err)
276
+
assert.ElementsMatch(t, []string{
280
+
spindles, err := e.GetSpindlesForUser("did:plc:foo")
281
+
assert.NoError(t, err)
282
+
assert.ElementsMatch(t, []string{
287
+
func TestAddSpindleAndRoles(t *testing.T) {
290
+
err := e.AddSpindle("s.com")
291
+
assert.NoError(t, err)
293
+
err = e.AddSpindleOwner("s.com", "did:plc:foo")
294
+
assert.NoError(t, err)
296
+
ok, err := e.IsSpindleOwner("did:plc:foo", "s.com")
297
+
assert.NoError(t, err)
300
+
ok, err = e.IsSpindleMember("did:plc:foo", "s.com")
301
+
assert.NoError(t, err)