Skip to content

Commit

Permalink
Add API to query collaborators permission for a repository (go-gitea#…
Browse files Browse the repository at this point in the history
…18761)

Targeting go-gitea#14936, go-gitea#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.

`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.
  • Loading branch information
flozzone authored and AbdulrhmnGhanem committed Aug 23, 2022
1 parent a0ccd6b commit 40eb3aa
Show file tree
Hide file tree
Showing 8 changed files with 312 additions and 1 deletion.
131 changes: 131 additions & 0 deletions integrations/api_repo_collaborator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package integrations

import (
"net/http"
"net/url"
"testing"

"code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"

"github.com/stretchr/testify/assert"
)

func TestAPIRepoCollaboratorPermission(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository)
repo2Owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo2.OwnerID}).(*user_model.User)

user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}).(*user_model.User)
user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}).(*user_model.User)
user10 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 10}).(*user_model.User)
user11 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 11}).(*user_model.User)

session := loginUser(t, repo2Owner.Name)
testCtx := NewAPITestContext(t, repo2Owner.Name, repo2.Name)

t.Run("RepoOwnerShouldBeOwner", func(t *testing.T) {
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, repo2Owner.Name, testCtx.Token)
resp := session.MakeRequest(t, req, http.StatusOK)

var repoPermission api.RepoCollaboratorPermission
DecodeJSON(t, resp, &repoPermission)

assert.Equal(t, "owner", repoPermission.Permission)
})

t.Run("CollaboratorWithReadAccess", func(t *testing.T) {
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeRead))

req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user4.Name, testCtx.Token)
resp := session.MakeRequest(t, req, http.StatusOK)

var repoPermission api.RepoCollaboratorPermission
DecodeJSON(t, resp, &repoPermission)

assert.Equal(t, "read", repoPermission.Permission)
})

t.Run("CollaboratorWithWriteAccess", func(t *testing.T) {
t.Run("AddUserAsCollaboratorWithWriteAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeWrite))

req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user4.Name, testCtx.Token)
resp := session.MakeRequest(t, req, http.StatusOK)

var repoPermission api.RepoCollaboratorPermission
DecodeJSON(t, resp, &repoPermission)

assert.Equal(t, "write", repoPermission.Permission)
})

t.Run("CollaboratorWithAdminAccess", func(t *testing.T) {
t.Run("AddUserAsCollaboratorWithAdminAccess", doAPIAddCollaborator(testCtx, user4.Name, perm.AccessModeAdmin))

req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user4.Name, testCtx.Token)
resp := session.MakeRequest(t, req, http.StatusOK)

var repoPermission api.RepoCollaboratorPermission
DecodeJSON(t, resp, &repoPermission)

assert.Equal(t, "admin", repoPermission.Permission)
})

t.Run("CollaboratorNotFound", func(t *testing.T) {
req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, "non-existent-user", testCtx.Token)
session.MakeRequest(t, req, http.StatusNotFound)
})

t.Run("CollaboratorCanQueryItsPermissions", func(t *testing.T) {
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))

_session := loginUser(t, user5.Name)
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name)

req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user5.Name, _testCtx.Token)
resp := _session.MakeRequest(t, req, http.StatusOK)

var repoPermission api.RepoCollaboratorPermission
DecodeJSON(t, resp, &repoPermission)

assert.Equal(t, "read", repoPermission.Permission)
})

t.Run("CollaboratorCanQueryItsPermissions", func(t *testing.T) {
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user5.Name, perm.AccessModeRead))

_session := loginUser(t, user5.Name)
_testCtx := NewAPITestContext(t, user5.Name, repo2.Name)

req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user5.Name, _testCtx.Token)
resp := _session.MakeRequest(t, req, http.StatusOK)

var repoPermission api.RepoCollaboratorPermission
DecodeJSON(t, resp, &repoPermission)

assert.Equal(t, "read", repoPermission.Permission)
})

t.Run("RepoAdminCanQueryACollaboratorsPermissions", func(t *testing.T) {
t.Run("AddUserAsCollaboratorWithAdminAccess", doAPIAddCollaborator(testCtx, user10.Name, perm.AccessModeAdmin))
t.Run("AddUserAsCollaboratorWithReadAccess", doAPIAddCollaborator(testCtx, user11.Name, perm.AccessModeRead))

_session := loginUser(t, user10.Name)
_testCtx := NewAPITestContext(t, user10.Name, repo2.Name)

req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission?token=%s", repo2Owner.Name, repo2.Name, user11.Name, _testCtx.Token)
resp := _session.MakeRequest(t, req, http.StatusOK)

var repoPermission api.RepoCollaboratorPermission
DecodeJSON(t, resp, &repoPermission)

assert.Equal(t, "read", repoPermission.Permission)
})
})
}
32 changes: 32 additions & 0 deletions models/fixtures/user.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
id: 1
lower_name: user1
name: user1
login_name: user1
full_name: User One
email: user1@example.com
email_notifications_preference: enabled
Expand All @@ -21,6 +22,7 @@
id: 2
lower_name: user2
name: user2
login_name: user2
full_name: " < U<se>r Tw<o > >< "
email: user2@example.com
keep_email_private: true
Expand All @@ -42,6 +44,7 @@
id: 3
lower_name: user3
name: user3
login_name: user3
full_name: " <<<< >> >> > >> > >>> >> "
email: user3@example.com
email_notifications_preference: onmention
Expand All @@ -60,6 +63,7 @@
id: 4
lower_name: user4
name: user4
login_name: user4
full_name: " "
email: user4@example.com
email_notifications_preference: onmention
Expand All @@ -78,6 +82,7 @@
id: 5
lower_name: user5
name: user5
login_name: user5
full_name: User Five
email: user5@example.com
email_notifications_preference: enabled
Expand All @@ -97,6 +102,7 @@
id: 6
lower_name: user6
name: user6
login_name: user6
full_name: User Six
email: user6@example.com
email_notifications_preference: enabled
Expand All @@ -115,6 +121,7 @@
id: 7
lower_name: user7
name: user7
login_name: user7
full_name: User Seven
email: user7@example.com
email_notifications_preference: disabled
Expand All @@ -133,6 +140,7 @@
id: 8
lower_name: user8
name: user8
login_name: user8
full_name: User Eight
email: user8@example.com
email_notifications_preference: enabled
Expand All @@ -152,6 +160,7 @@
id: 9
lower_name: user9
name: user9
login_name: user9
full_name: User Nine
email: user9@example.com
email_notifications_preference: onmention
Expand All @@ -169,6 +178,7 @@
id: 10
lower_name: user10
name: user10
login_name: user10
full_name: User Ten
email: user10@example.com
passwd_hash_algo: argon2
Expand All @@ -185,6 +195,7 @@
id: 11
lower_name: user11
name: user11
login_name: user11
full_name: User Eleven
email: user11@example.com
passwd_hash_algo: argon2
Expand All @@ -201,6 +212,7 @@
id: 12
lower_name: user12
name: user12
login_name: user12
full_name: User 12
email: user12@example.com
passwd_hash_algo: argon2
Expand All @@ -217,6 +229,7 @@
id: 13
lower_name: user13
name: user13
login_name: user13
full_name: User 13
email: user13@example.com
passwd_hash_algo: argon2
Expand All @@ -233,6 +246,7 @@
id: 14
lower_name: user14
name: user14
login_name: user14
full_name: User 14
email: user14@example.com
passwd_hash_algo: argon2
Expand All @@ -249,6 +263,7 @@
id: 15
lower_name: user15
name: user15
login_name: user15
full_name: User 15
email: user15@example.com
passwd_hash_algo: argon2
Expand All @@ -265,6 +280,7 @@
id: 16
lower_name: user16
name: user16
login_name: user16
full_name: User 16
email: user16@example.com
passwd_hash_algo: argon2
Expand All @@ -281,6 +297,7 @@
id: 17
lower_name: user17
name: user17
login_name: user17
full_name: User 17
email: user17@example.com
passwd_hash_algo: argon2
Expand All @@ -299,6 +316,7 @@
id: 18
lower_name: user18
name: user18
login_name: user18
full_name: User 18
email: user18@example.com
passwd_hash_algo: argon2
Expand All @@ -315,6 +333,7 @@
id: 19
lower_name: user19
name: user19
login_name: user19
full_name: User 19
email: user19@example.com
passwd_hash_algo: argon2
Expand All @@ -333,6 +352,7 @@
id: 20
lower_name: user20
name: user20
login_name: user20
full_name: User 20
email: user20@example.com
passwd_hash_algo: argon2
Expand All @@ -349,6 +369,7 @@
id: 21
lower_name: user21
name: user21
login_name: user21
full_name: User 21
email: user21@example.com
passwd_hash_algo: argon2
Expand All @@ -365,6 +386,7 @@
id: 22
lower_name: limited_org
name: limited_org
login_name: limited_org
full_name: Limited Org
email: limited_org@example.com
passwd_hash_algo: argon2
Expand All @@ -384,6 +406,7 @@
id: 23
lower_name: privated_org
name: privated_org
login_name: privated_org
full_name: Privated Org
email: privated_org@example.com
passwd_hash_algo: argon2
Expand All @@ -403,6 +426,7 @@
id: 24
lower_name: user24
name: user24
login_name: user24
full_name: "user24"
email: user24@example.com
keep_email_private: true
Expand All @@ -423,6 +447,7 @@
id: 25
lower_name: org25
name: org25
login_name: org25
full_name: "org25"
email: org25@example.com
passwd_hash_algo: argon2
Expand All @@ -440,6 +465,7 @@
id: 26
lower_name: org26
name: org26
login_name: org26
full_name: "Org26"
email: org26@example.com
email_notifications_preference: onmention
Expand All @@ -459,6 +485,7 @@
id: 27
lower_name: user27
name: user27
login_name: user27
full_name: User Twenty-Seven
email: user27@example.com
email_notifications_preference: enabled
Expand All @@ -475,6 +502,7 @@
id: 28
lower_name: user28
name: user28
login_name: user28
full_name: "user27"
email: user28@example.com
keep_email_private: true
Expand All @@ -495,6 +523,7 @@
id: 29
lower_name: user29
name: user29
login_name: user29
full_name: User 29
email: user29@example.com
passwd_hash_algo: argon2
Expand All @@ -512,6 +541,7 @@
id: 30
lower_name: user30
name: user30
login_name: user30
full_name: User Thirty
email: user30@example.com
passwd_hash_algo: argon2
Expand All @@ -530,6 +560,7 @@
id: 31
lower_name: user31
name: user31
login_name: user31
full_name: "user31"
email: user31@example.com
passwd_hash_algo: argon2
Expand All @@ -547,6 +578,7 @@
id: 32
lower_name: user32
name: user32
login_name: user32
full_name: User 32 (U2F test)
email: user32@example.com
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password
Expand Down
Loading

0 comments on commit 40eb3aa

Please sign in to comment.