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.
This commit is contained in:
parent
e5c6c001c5
commit
ad6d08d155
8 changed files with 317 additions and 3 deletions
131
integrations/api_repo_collaborator_test.go
Normal file
131
integrations/api_repo_collaborator_test.go
Normal file
|
@ -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)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
id: 1
|
id: 1
|
||||||
lower_name: user1
|
lower_name: user1
|
||||||
name: user1
|
name: user1
|
||||||
|
login_name: user1
|
||||||
full_name: User One
|
full_name: User One
|
||||||
email: user1@example.com
|
email: user1@example.com
|
||||||
email_notifications_preference: enabled
|
email_notifications_preference: enabled
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
id: 2
|
id: 2
|
||||||
lower_name: user2
|
lower_name: user2
|
||||||
name: user2
|
name: user2
|
||||||
|
login_name: user2
|
||||||
full_name: " < U<se>r Tw<o > >< "
|
full_name: " < U<se>r Tw<o > >< "
|
||||||
email: user2@example.com
|
email: user2@example.com
|
||||||
keep_email_private: true
|
keep_email_private: true
|
||||||
|
@ -42,6 +44,7 @@
|
||||||
id: 3
|
id: 3
|
||||||
lower_name: user3
|
lower_name: user3
|
||||||
name: user3
|
name: user3
|
||||||
|
login_name: user3
|
||||||
full_name: " <<<< >> >> > >> > >>> >> "
|
full_name: " <<<< >> >> > >> > >>> >> "
|
||||||
email: user3@example.com
|
email: user3@example.com
|
||||||
email_notifications_preference: onmention
|
email_notifications_preference: onmention
|
||||||
|
@ -60,6 +63,7 @@
|
||||||
id: 4
|
id: 4
|
||||||
lower_name: user4
|
lower_name: user4
|
||||||
name: user4
|
name: user4
|
||||||
|
login_name: user4
|
||||||
full_name: " "
|
full_name: " "
|
||||||
email: user4@example.com
|
email: user4@example.com
|
||||||
email_notifications_preference: onmention
|
email_notifications_preference: onmention
|
||||||
|
@ -78,6 +82,7 @@
|
||||||
id: 5
|
id: 5
|
||||||
lower_name: user5
|
lower_name: user5
|
||||||
name: user5
|
name: user5
|
||||||
|
login_name: user5
|
||||||
full_name: User Five
|
full_name: User Five
|
||||||
email: user5@example.com
|
email: user5@example.com
|
||||||
email_notifications_preference: enabled
|
email_notifications_preference: enabled
|
||||||
|
@ -97,6 +102,7 @@
|
||||||
id: 6
|
id: 6
|
||||||
lower_name: user6
|
lower_name: user6
|
||||||
name: user6
|
name: user6
|
||||||
|
login_name: user6
|
||||||
full_name: User Six
|
full_name: User Six
|
||||||
email: user6@example.com
|
email: user6@example.com
|
||||||
email_notifications_preference: enabled
|
email_notifications_preference: enabled
|
||||||
|
@ -115,6 +121,7 @@
|
||||||
id: 7
|
id: 7
|
||||||
lower_name: user7
|
lower_name: user7
|
||||||
name: user7
|
name: user7
|
||||||
|
login_name: user7
|
||||||
full_name: User Seven
|
full_name: User Seven
|
||||||
email: user7@example.com
|
email: user7@example.com
|
||||||
email_notifications_preference: disabled
|
email_notifications_preference: disabled
|
||||||
|
@ -133,6 +140,7 @@
|
||||||
id: 8
|
id: 8
|
||||||
lower_name: user8
|
lower_name: user8
|
||||||
name: user8
|
name: user8
|
||||||
|
login_name: user8
|
||||||
full_name: User Eight
|
full_name: User Eight
|
||||||
email: user8@example.com
|
email: user8@example.com
|
||||||
email_notifications_preference: enabled
|
email_notifications_preference: enabled
|
||||||
|
@ -152,6 +160,7 @@
|
||||||
id: 9
|
id: 9
|
||||||
lower_name: user9
|
lower_name: user9
|
||||||
name: user9
|
name: user9
|
||||||
|
login_name: user9
|
||||||
full_name: User Nine
|
full_name: User Nine
|
||||||
email: user9@example.com
|
email: user9@example.com
|
||||||
email_notifications_preference: onmention
|
email_notifications_preference: onmention
|
||||||
|
@ -169,6 +178,7 @@
|
||||||
id: 10
|
id: 10
|
||||||
lower_name: user10
|
lower_name: user10
|
||||||
name: user10
|
name: user10
|
||||||
|
login_name: user10
|
||||||
full_name: User Ten
|
full_name: User Ten
|
||||||
email: user10@example.com
|
email: user10@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -185,6 +195,7 @@
|
||||||
id: 11
|
id: 11
|
||||||
lower_name: user11
|
lower_name: user11
|
||||||
name: user11
|
name: user11
|
||||||
|
login_name: user11
|
||||||
full_name: User Eleven
|
full_name: User Eleven
|
||||||
email: user11@example.com
|
email: user11@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -201,6 +212,7 @@
|
||||||
id: 12
|
id: 12
|
||||||
lower_name: user12
|
lower_name: user12
|
||||||
name: user12
|
name: user12
|
||||||
|
login_name: user12
|
||||||
full_name: User 12
|
full_name: User 12
|
||||||
email: user12@example.com
|
email: user12@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -217,6 +229,7 @@
|
||||||
id: 13
|
id: 13
|
||||||
lower_name: user13
|
lower_name: user13
|
||||||
name: user13
|
name: user13
|
||||||
|
login_name: user13
|
||||||
full_name: User 13
|
full_name: User 13
|
||||||
email: user13@example.com
|
email: user13@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -233,6 +246,7 @@
|
||||||
id: 14
|
id: 14
|
||||||
lower_name: user14
|
lower_name: user14
|
||||||
name: user14
|
name: user14
|
||||||
|
login_name: user14
|
||||||
full_name: User 14
|
full_name: User 14
|
||||||
email: user14@example.com
|
email: user14@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -249,6 +263,7 @@
|
||||||
id: 15
|
id: 15
|
||||||
lower_name: user15
|
lower_name: user15
|
||||||
name: user15
|
name: user15
|
||||||
|
login_name: user15
|
||||||
full_name: User 15
|
full_name: User 15
|
||||||
email: user15@example.com
|
email: user15@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -265,6 +280,7 @@
|
||||||
id: 16
|
id: 16
|
||||||
lower_name: user16
|
lower_name: user16
|
||||||
name: user16
|
name: user16
|
||||||
|
login_name: user16
|
||||||
full_name: User 16
|
full_name: User 16
|
||||||
email: user16@example.com
|
email: user16@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -281,6 +297,7 @@
|
||||||
id: 17
|
id: 17
|
||||||
lower_name: user17
|
lower_name: user17
|
||||||
name: user17
|
name: user17
|
||||||
|
login_name: user17
|
||||||
full_name: User 17
|
full_name: User 17
|
||||||
email: user17@example.com
|
email: user17@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -299,6 +316,7 @@
|
||||||
id: 18
|
id: 18
|
||||||
lower_name: user18
|
lower_name: user18
|
||||||
name: user18
|
name: user18
|
||||||
|
login_name: user18
|
||||||
full_name: User 18
|
full_name: User 18
|
||||||
email: user18@example.com
|
email: user18@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -315,6 +333,7 @@
|
||||||
id: 19
|
id: 19
|
||||||
lower_name: user19
|
lower_name: user19
|
||||||
name: user19
|
name: user19
|
||||||
|
login_name: user19
|
||||||
full_name: User 19
|
full_name: User 19
|
||||||
email: user19@example.com
|
email: user19@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -333,6 +352,7 @@
|
||||||
id: 20
|
id: 20
|
||||||
lower_name: user20
|
lower_name: user20
|
||||||
name: user20
|
name: user20
|
||||||
|
login_name: user20
|
||||||
full_name: User 20
|
full_name: User 20
|
||||||
email: user20@example.com
|
email: user20@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -349,6 +369,7 @@
|
||||||
id: 21
|
id: 21
|
||||||
lower_name: user21
|
lower_name: user21
|
||||||
name: user21
|
name: user21
|
||||||
|
login_name: user21
|
||||||
full_name: User 21
|
full_name: User 21
|
||||||
email: user21@example.com
|
email: user21@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -365,6 +386,7 @@
|
||||||
id: 22
|
id: 22
|
||||||
lower_name: limited_org
|
lower_name: limited_org
|
||||||
name: limited_org
|
name: limited_org
|
||||||
|
login_name: limited_org
|
||||||
full_name: Limited Org
|
full_name: Limited Org
|
||||||
email: limited_org@example.com
|
email: limited_org@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -384,6 +406,7 @@
|
||||||
id: 23
|
id: 23
|
||||||
lower_name: privated_org
|
lower_name: privated_org
|
||||||
name: privated_org
|
name: privated_org
|
||||||
|
login_name: privated_org
|
||||||
full_name: Privated Org
|
full_name: Privated Org
|
||||||
email: privated_org@example.com
|
email: privated_org@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -403,6 +426,7 @@
|
||||||
id: 24
|
id: 24
|
||||||
lower_name: user24
|
lower_name: user24
|
||||||
name: user24
|
name: user24
|
||||||
|
login_name: user24
|
||||||
full_name: "user24"
|
full_name: "user24"
|
||||||
email: user24@example.com
|
email: user24@example.com
|
||||||
keep_email_private: true
|
keep_email_private: true
|
||||||
|
@ -423,6 +447,7 @@
|
||||||
id: 25
|
id: 25
|
||||||
lower_name: org25
|
lower_name: org25
|
||||||
name: org25
|
name: org25
|
||||||
|
login_name: org25
|
||||||
full_name: "org25"
|
full_name: "org25"
|
||||||
email: org25@example.com
|
email: org25@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -440,6 +465,7 @@
|
||||||
id: 26
|
id: 26
|
||||||
lower_name: org26
|
lower_name: org26
|
||||||
name: org26
|
name: org26
|
||||||
|
login_name: org26
|
||||||
full_name: "Org26"
|
full_name: "Org26"
|
||||||
email: org26@example.com
|
email: org26@example.com
|
||||||
email_notifications_preference: onmention
|
email_notifications_preference: onmention
|
||||||
|
@ -459,6 +485,7 @@
|
||||||
id: 27
|
id: 27
|
||||||
lower_name: user27
|
lower_name: user27
|
||||||
name: user27
|
name: user27
|
||||||
|
login_name: user27
|
||||||
full_name: User Twenty-Seven
|
full_name: User Twenty-Seven
|
||||||
email: user27@example.com
|
email: user27@example.com
|
||||||
email_notifications_preference: enabled
|
email_notifications_preference: enabled
|
||||||
|
@ -475,6 +502,7 @@
|
||||||
id: 28
|
id: 28
|
||||||
lower_name: user28
|
lower_name: user28
|
||||||
name: user28
|
name: user28
|
||||||
|
login_name: user28
|
||||||
full_name: "user27"
|
full_name: "user27"
|
||||||
email: user28@example.com
|
email: user28@example.com
|
||||||
keep_email_private: true
|
keep_email_private: true
|
||||||
|
@ -495,6 +523,7 @@
|
||||||
id: 29
|
id: 29
|
||||||
lower_name: user29
|
lower_name: user29
|
||||||
name: user29
|
name: user29
|
||||||
|
login_name: user29
|
||||||
full_name: User 29
|
full_name: User 29
|
||||||
email: user29@example.com
|
email: user29@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -512,6 +541,7 @@
|
||||||
id: 30
|
id: 30
|
||||||
lower_name: user30
|
lower_name: user30
|
||||||
name: user30
|
name: user30
|
||||||
|
login_name: user30
|
||||||
full_name: User Thirty
|
full_name: User Thirty
|
||||||
email: user30@example.com
|
email: user30@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -530,6 +560,7 @@
|
||||||
id: 31
|
id: 31
|
||||||
lower_name: user31
|
lower_name: user31
|
||||||
name: user31
|
name: user31
|
||||||
|
login_name: user31
|
||||||
full_name: "user31"
|
full_name: "user31"
|
||||||
email: user31@example.com
|
email: user31@example.com
|
||||||
passwd_hash_algo: argon2
|
passwd_hash_algo: argon2
|
||||||
|
@ -547,6 +578,7 @@
|
||||||
id: 32
|
id: 32
|
||||||
lower_name: user32
|
lower_name: user32
|
||||||
name: user32
|
name: user32
|
||||||
|
login_name: user32
|
||||||
full_name: User 32 (U2F test)
|
full_name: User 32 (U2F test)
|
||||||
email: user32@example.com
|
email: user32@example.com
|
||||||
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password
|
passwd: 7d93daa0d1e6f2305cc8fa496847d61dc7320bb16262f9c55dd753480207234cdd96a93194e408341971742f4701772a025a # password
|
||||||
|
|
|
@ -95,3 +95,12 @@ func User2UserSettings(user *user_model.User) api.UserSettings {
|
||||||
DiffViewStyle: user.DiffViewStyle,
|
DiffViewStyle: user.DiffViewStyle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToUserAndPermission return User and its collaboration permission for a repository
|
||||||
|
func ToUserAndPermission(user, doer *user_model.User, accessMode perm.AccessMode) api.RepoCollaboratorPermission {
|
||||||
|
return api.RepoCollaboratorPermission{
|
||||||
|
User: ToUser(user, doer),
|
||||||
|
Permission: accessMode.String(),
|
||||||
|
RoleName: accessMode.String(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,3 +8,10 @@ package structs
|
||||||
type AddCollaboratorOption struct {
|
type AddCollaboratorOption struct {
|
||||||
Permission *string `json:"permission"`
|
Permission *string `json:"permission"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RepoCollaboratorPermission to get repository permission for a collaborator
|
||||||
|
type RepoCollaboratorPermission struct {
|
||||||
|
Permission string `json:"permission"`
|
||||||
|
RoleName string `json:"role_name"`
|
||||||
|
User *User `json:"user"`
|
||||||
|
}
|
||||||
|
|
|
@ -810,9 +810,12 @@ func Routes() *web.Route {
|
||||||
}, reqToken(), reqAdmin(), reqWebhooksEnabled())
|
}, reqToken(), reqAdmin(), reqWebhooksEnabled())
|
||||||
m.Group("/collaborators", func() {
|
m.Group("/collaborators", func() {
|
||||||
m.Get("", reqAnyRepoReader(), repo.ListCollaborators)
|
m.Get("", reqAnyRepoReader(), repo.ListCollaborators)
|
||||||
m.Combo("/{collaborator}").Get(reqAnyRepoReader(), repo.IsCollaborator).
|
m.Group("/{collaborator}", func() {
|
||||||
Put(reqAdmin(), bind(api.AddCollaboratorOption{}), repo.AddCollaborator).
|
m.Combo("").Get(reqAnyRepoReader(), repo.IsCollaborator).
|
||||||
Delete(reqAdmin(), repo.DeleteCollaborator)
|
Put(reqAdmin(), bind(api.AddCollaboratorOption{}), repo.AddCollaborator).
|
||||||
|
Delete(reqAdmin(), repo.DeleteCollaborator)
|
||||||
|
m.Get("/permission", repo.GetRepoPermissions)
|
||||||
|
}, reqToken())
|
||||||
}, reqToken())
|
}, reqToken())
|
||||||
m.Get("/assignees", reqToken(), reqAnyRepoReader(), repo.GetAssignees)
|
m.Get("/assignees", reqToken(), reqAnyRepoReader(), repo.GetAssignees)
|
||||||
m.Get("/reviewers", reqToken(), reqAnyRepoReader(), repo.GetReviewers)
|
m.Get("/reviewers", reqToken(), reqAnyRepoReader(), repo.GetReviewers)
|
||||||
|
|
|
@ -233,6 +233,61 @@ func DeleteCollaborator(ctx *context.APIContext) {
|
||||||
ctx.Status(http.StatusNoContent)
|
ctx.Status(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRepoPermissions gets repository permissions for a user
|
||||||
|
func GetRepoPermissions(ctx *context.APIContext) {
|
||||||
|
// swagger:operation GET /repos/{owner}/{repo}/collaborators/{collaborator}/permission repository repoGetRepoPermissions
|
||||||
|
// ---
|
||||||
|
// summary: Get repository permissions for a user
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: owner
|
||||||
|
// in: path
|
||||||
|
// description: owner of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: repo
|
||||||
|
// in: path
|
||||||
|
// description: name of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: collaborator
|
||||||
|
// in: path
|
||||||
|
// description: username of the collaborator
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/RepoCollaboratorPermission"
|
||||||
|
// "404":
|
||||||
|
// "$ref": "#/responses/notFound"
|
||||||
|
// "403":
|
||||||
|
// "$ref": "#/responses/forbidden"
|
||||||
|
|
||||||
|
if !ctx.Doer.IsAdmin && ctx.Doer.LoginName != ctx.Params(":collaborator") && !ctx.IsUserRepoAdmin() {
|
||||||
|
ctx.Error(http.StatusForbidden, "User", "Only admins can query all permissions, repo admins can query all repo permissions, collaborators can query only their own")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
collaborator, err := user_model.GetUserByName(ctx.Params(":collaborator"))
|
||||||
|
if err != nil {
|
||||||
|
if user_model.IsErrUserNotExist(err) {
|
||||||
|
ctx.Error(http.StatusNotFound, "GetUserByName", err)
|
||||||
|
} else {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetUserByName", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
permission, err := models.GetUserRepoPermission(ctx, ctx.Repo.Repository, collaborator)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, convert.ToUserAndPermission(collaborator, ctx.ContextUser, permission.AccessMode))
|
||||||
|
}
|
||||||
|
|
||||||
// GetReviewers return all users that can be requested to review in this repo
|
// GetReviewers return all users that can be requested to review in this repo
|
||||||
func GetReviewers(ctx *context.APIContext) {
|
func GetReviewers(ctx *context.APIContext) {
|
||||||
// swagger:operation GET /repos/{owner}/{repo}/reviewers repository repoGetReviewers
|
// swagger:operation GET /repos/{owner}/{repo}/reviewers repository repoGetReviewers
|
||||||
|
|
|
@ -344,3 +344,10 @@ type swaggerWikiCommitList struct {
|
||||||
// in:body
|
// in:body
|
||||||
Body api.WikiCommitList `json:"body"`
|
Body api.WikiCommitList `json:"body"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RepoCollaboratorPermission
|
||||||
|
// swagger:response RepoCollaboratorPermission
|
||||||
|
type swaggerRepoCollaboratorPermission struct {
|
||||||
|
// in:body
|
||||||
|
Body api.RepoCollaboratorPermission `json:"body"`
|
||||||
|
}
|
||||||
|
|
|
@ -3129,6 +3129,52 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/repos/{owner}/{repo}/collaborators/{collaborator}/permission": {
|
||||||
|
"get": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"repository"
|
||||||
|
],
|
||||||
|
"summary": "Get repository permissions for a user",
|
||||||
|
"operationId": "repoGetRepoPermissions",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "owner of the repo",
|
||||||
|
"name": "owner",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the repo",
|
||||||
|
"name": "repo",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "username of the collaborator",
|
||||||
|
"name": "collaborator",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/RepoCollaboratorPermission"
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"$ref": "#/responses/forbidden"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFound"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/repos/{owner}/{repo}/commits": {
|
"/repos/{owner}/{repo}/commits": {
|
||||||
"get": {
|
"get": {
|
||||||
"produces": [
|
"produces": [
|
||||||
|
@ -17451,6 +17497,24 @@
|
||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
},
|
},
|
||||||
|
"RepoCollaboratorPermission": {
|
||||||
|
"description": "RepoCollaboratorPermission to get repository permission for a collaborator",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"permission": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "Permission"
|
||||||
|
},
|
||||||
|
"role_name": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "RoleName"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"$ref": "#/definitions/User"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
},
|
||||||
"RepoCommit": {
|
"RepoCommit": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"title": "RepoCommit contains information of a commit in the context of a repository.",
|
"title": "RepoCommit contains information of a commit in the context of a repository.",
|
||||||
|
@ -19126,6 +19190,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"RepoCollaboratorPermission": {
|
||||||
|
"description": "RepoCollaboratorPermission",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/RepoCollaboratorPermission"
|
||||||
|
}
|
||||||
|
},
|
||||||
"Repository": {
|
"Repository": {
|
||||||
"description": "Repository",
|
"description": "Repository",
|
||||||
"schema": {
|
"schema": {
|
||||||
|
|
Reference in a new issue