Skip to content

Commit ad6d08d

Browse files
authored
Add API to query collaborators permission for a repository (#18761)
Targeting #14936, #15332 Adds a collaborator permissions API endpoint according to GitHub API: https://docs.github.com/en/rest/collaborators/collaborators#get-repository-permissions-for-a-user to retrieve a collaborators permissions for a specific repository. ### Checks the repository permissions of a collaborator. `GET` `/repos/{owner}/{repo}/collaborators/{collaborator}/permission` Possible `permission` values are `admin`, `write`, `read`, `owner`, `none`. ```json { "permission": "admin", "role_name": "admin", "user": {} } ``` Where `permission` and `role_name` hold the same `permission` value and `user` is filled with the user API object. Only admins are allowed to use this API endpoint.
1 parent e5c6c00 commit ad6d08d

File tree

8 files changed

+317
-3
lines changed

8 files changed

+317
-3
lines changed
+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package integrations
6+
7+
import (
8+
"net/http"
9+
"net/url"
10+
"testing"
11+
12+
"code.gitea.io/gitea/models/perm"
13+
repo_model "code.gitea.io/gitea/models/repo"
14+
"code.gitea.io/gitea/models/unittest"
15+
user_model "code.gitea.io/gitea/models/user"
16+
api "code.gitea.io/gitea/modules/structs"
17+
18+
"github.com/stretchr/testify/assert"
19+
)
20+
21+
func TestAPIRepoCollaboratorPermission(t *testing.T) {
22+
onGiteaRun(t, func(t *testing.T, u *url.URL) {
23+
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository)
24+
repo2Owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo2.OwnerID}).(*user_model.User)
25+
26+
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}).(*user_model.User)
27+
user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}).(*user_model.User)
28+
user10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 10}).(*user_model.User)
29+
user11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 11}).(*user_model.User)
30+
31+
session := loginUser(t, repo2Owner.Name)
32+
testCtx := NewAPITestContext(t, repo2Owner.Name, repo2.Name)
33+
34+
t.Run("RepoOwnerShouldBeOwner", func(t *testing.T) {
35+
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, repo2Owner.Name, testCtx.Token)
36+
resp := session.MakeRequest(t, req, http.StatusOK)
37+
38+
var repoPermission api.RepoCollaboratorPermission
39+
DecodeJSON(t, resp, &repoPermission)
40+
41+
assert.Equal(t, "owner", repoPermission.Permission)
42+
})
43+
44+
t.Run("CollaboratorWithReadAccess", func(t *testing.T) {
45+
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeRead))
46+
47+
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user4.Name, testCtx.Token)
48+
resp := session.MakeRequest(t, req, http.StatusOK)
49+
50+
var repoPermission api.RepoCollaboratorPermission
51+
DecodeJSON(t, resp, &repoPermission)
52+
53+
assert.Equal(t, "read", repoPermission.Permission)
54+
})
55+
56+
t.Run("CollaboratorWithWriteAccess", func(t *testing.T) {
57+
t.Run("AddUserAsCollaboratorWithWriteAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeWrite))
58+
59+
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user4.Name, testCtx.Token)
60+
resp := session.MakeRequest(t, req, http.StatusOK)
61+
62+
var repoPermission api.RepoCollaboratorPermission
63+
DecodeJSON(t, resp, &repoPermission)
64+
65+
assert.Equal(t, "write", repoPermission.Permission)
66+
})
67+
68+
t.Run("CollaboratorWithAdminAccess", func(t *testing.T) {
69+
t.Run("AddUserAsCollaboratorWithAdminAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeAdmin))
70+
71+
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user4.Name, testCtx.Token)
72+
resp := session.MakeRequest(t, req, http.StatusOK)
73+
74+
var repoPermission api.RepoCollaboratorPermission
75+
DecodeJSON(t, resp, &repoPermission)
76+
77+
assert.Equal(t, "admin", repoPermission.Permission)
78+
})
79+
80+
t.Run("CollaboratorNotFound", func(t *testing.T) {
81+
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, "non-existent-user", testCtx.Token)
82+
session.MakeRequest(t, req, http.StatusNotFound)
83+
})
84+
85+
t.Run("CollaboratorCanQueryItsPermissions", func(t *testing.T) {
86+
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
87+
88+
_session := loginUser(t, user5.Name)
89+
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name)
90+
91+
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user5.Name, _testCtx.Token)
92+
resp := _session.MakeRequest(t, req, http.StatusOK)
93+
94+
var repoPermission api.RepoCollaboratorPermission
95+
DecodeJSON(t, resp, &repoPermission)
96+
97+
assert.Equal(t, "read", repoPermission.Permission)
98+
})
99+
100+
t.Run("CollaboratorCanQueryItsPermissions", func(t *testing.T) {
101+
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))
102+
103+
_session := loginUser(t, user5.Name)
104+
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name)
105+
106+
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user5.Name, _testCtx.Token)
107+
resp := _session.MakeRequest(t, req, http.StatusOK)
108+
109+
var repoPermission api.RepoCollaboratorPermission
110+
DecodeJSON(t, resp, &repoPermission)
111+
112+
assert.Equal(t, "read", repoPermission.Permission)
113+
})
114+
115+
t.Run("RepoAdminCanQueryACollaboratorsPermissions", func(t *testing.T) {
116+
t.Run("AddUserAsCollaboratorWithAdminAccess", doAPIAddCollaborator(testCtx, user10.Name, perm.AccessModeAdmin))
117+
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user11.Name, perm.AccessModeRead))
118+
119+
_session := loginUser(t, user10.Name)
120+
_testCtx := NewAPITestContext(t, user10.Name, repo2.Name)
121+
122+
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user11.Name, _testCtx.Token)
123+
resp := _session.MakeRequest(t, req, http.StatusOK)
124+
125+
var repoPermission api.RepoCollaboratorPermission
126+
DecodeJSON(t, resp, &repoPermission)
127+
128+
assert.Equal(t, "read", repoPermission.Permission)
129+
})
130+
})
131+
}

models/fixtures/user.yml

+32
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
id: 1
55
lower_name: user1
66
name: user1
7+
login_name: user1
78
full_name: User One
89
910
email_notifications_preference: enabled
@@ -21,6 +22,7 @@
2122
id: 2
2223
lower_name: user2
2324
name: user2
25+
login_name: user2
2426
full_name: " < U<se>r Tw<o > >< "
2527
2628
keep_email_private: true
@@ -42,6 +44,7 @@
4244
id: 3
4345
lower_name: user3
4446
name: user3
47+
login_name: user3
4548
full_name: " <<<< >> >> > >> > >>> >> "
4649
4750
email_notifications_preference: onmention
@@ -60,6 +63,7 @@
6063
id: 4
6164
lower_name: user4
6265
name: user4
66+
login_name: user4
6367
full_name: " "
6468
6569
email_notifications_preference: onmention
@@ -78,6 +82,7 @@
7882
id: 5
7983
lower_name: user5
8084
name: user5
85+
login_name: user5
8186
full_name: User Five
8287
8388
email_notifications_preference: enabled
@@ -97,6 +102,7 @@
97102
id: 6
98103
lower_name: user6
99104
name: user6
105+
login_name: user6
100106
full_name: User Six
101107
102108
email_notifications_preference: enabled
@@ -115,6 +121,7 @@
115121
id: 7
116122
lower_name: user7
117123
name: user7
124+
login_name: user7
118125
full_name: User Seven
119126
120127
email_notifications_preference: disabled
@@ -133,6 +140,7 @@
133140
id: 8
134141
lower_name: user8
135142
name: user8
143+
login_name: user8
136144
full_name: User Eight
137145
138146
email_notifications_preference: enabled
@@ -152,6 +160,7 @@
152160
id: 9
153161
lower_name: user9
154162
name: user9
163+
login_name: user9
155164
full_name: User Nine
156165
157166
email_notifications_preference: onmention
@@ -169,6 +178,7 @@
169178
id: 10
170179
lower_name: user10
171180
name: user10
181+
login_name: user10
172182
full_name: User Ten
173183
174184
passwd_hash_algo: argon2
@@ -185,6 +195,7 @@
185195
id: 11
186196
lower_name: user11
187197
name: user11
198+
login_name: user11
188199
full_name: User Eleven
189200
190201
passwd_hash_algo: argon2
@@ -201,6 +212,7 @@
201212
id: 12
202213
lower_name: user12
203214
name: user12
215+
login_name: user12
204216
full_name: User 12
205217
206218
passwd_hash_algo: argon2
@@ -217,6 +229,7 @@
217229
id: 13
218230
lower_name: user13
219231
name: user13
232+
login_name: user13
220233
full_name: User 13
221234
222235
passwd_hash_algo: argon2
@@ -233,6 +246,7 @@
233246
id: 14
234247
lower_name: user14
235248
name: user14
249+
login_name: user14
236250
full_name: User 14
237251
238252
passwd_hash_algo: argon2
@@ -249,6 +263,7 @@
249263
id: 15
250264
lower_name: user15
251265
name: user15
266+
login_name: user15
252267
full_name: User 15
253268
254269
passwd_hash_algo: argon2
@@ -265,6 +280,7 @@
265280
id: 16
266281
lower_name: user16
267282
name: user16
283+
login_name: user16
268284
full_name: User 16
269285
270286
passwd_hash_algo: argon2
@@ -281,6 +297,7 @@
281297
id: 17
282298
lower_name: user17
283299
name: user17
300+
login_name: user17
284301
full_name: User 17
285302
286303
passwd_hash_algo: argon2
@@ -299,6 +316,7 @@
299316
id: 18
300317
lower_name: user18
301318
name: user18
319+
login_name: user18
302320
full_name: User 18
303321
304322
passwd_hash_algo: argon2
@@ -315,6 +333,7 @@
315333
id: 19
316334
lower_name: user19
317335
name: user19
336+
login_name: user19
318337
full_name: User 19
319338
320339
passwd_hash_algo: argon2
@@ -333,6 +352,7 @@
333352
id: 20
334353
lower_name: user20
335354
name: user20
355+
login_name: user20
336356
full_name: User 20
337357
338358
passwd_hash_algo: argon2
@@ -349,6 +369,7 @@
349369
id: 21
350370
lower_name: user21
351371
name: user21
372+
login_name: user21
352373
full_name: User 21
353374
354375
passwd_hash_algo: argon2
@@ -365,6 +386,7 @@
365386
id: 22
366387
lower_name: limited_org
367388
name: limited_org
389+
login_name: limited_org
368390
full_name: Limited Org
369391
370392
passwd_hash_algo: argon2
@@ -384,6 +406,7 @@
384406
id: 23
385407
lower_name: privated_org
386408
name: privated_org
409+
login_name: privated_org
387410
full_name: Privated Org
388411
389412
passwd_hash_algo: argon2
@@ -403,6 +426,7 @@
403426
id: 24
404427
lower_name: user24
405428
name: user24
429+
login_name: user24
406430
full_name: "user24"
407431
408432
keep_email_private: true
@@ -423,6 +447,7 @@
423447
id: 25
424448
lower_name: org25
425449
name: org25
450+
login_name: org25
426451
full_name: "org25"
427452
428453
passwd_hash_algo: argon2
@@ -440,6 +465,7 @@
440465
id: 26
441466
lower_name: org26
442467
name: org26
468+
login_name: org26
443469
full_name: "Org26"
444470
445471
email_notifications_preference: onmention
@@ -459,6 +485,7 @@
459485
id: 27
460486
lower_name: user27
461487
name: user27
488+
login_name: user27
462489
full_name: User Twenty-Seven
463490
464491
email_notifications_preference: enabled
@@ -475,6 +502,7 @@
475502
id: 28
476503
lower_name: user28
477504
name: user28
505+
login_name: user28
478506
full_name: "user27"
479507
480508
keep_email_private: true
@@ -495,6 +523,7 @@
495523
id: 29
496524
lower_name: user29
497525
name: user29
526+
login_name: user29
498527
full_name: User 29
499528
500529
passwd_hash_algo: argon2
@@ -512,6 +541,7 @@
512541
id: 30
513542
lower_name: user30
514543
name: user30
544+
login_name: user30
515545
full_name: User Thirty
516546
517547
passwd_hash_algo: argon2
@@ -530,6 +560,7 @@
530560
id: 31
531561
lower_name: user31
532562
name: user31
563+
login_name: user31
533564
full_name: "user31"
534565
535566
passwd_hash_algo: argon2
@@ -547,6 +578,7 @@
547578
id: 32
548579
lower_name: user32
549580
name: user32
581+
login_name: user32
550582
full_name: User 32 (U2F test)
551583
552584
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password

0 commit comments

Comments
 (0)