+303
rbac/rbac_test.go
+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
+
}