From 751a3da979db06adc99cc64fac6aad9505fd5a96 Mon Sep 17 00:00:00 2001 From: Gusted Date: Sat, 8 Feb 2025 15:09:08 +0000 Subject: [PATCH] fix(api): allow collaborators to read their own permissions (#6856) - Instead of checking the login name (which is not set in most cases and really the wrong thing to do here just like it is case sensitive) simply check that the requested user has the same ID as the doer. - Resolves forgejo/forgejo#6837 - Add integration test. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/6856 Reviewed-by: Earl Warren Reviewed-by: 0ko <0ko@noreply.codeberg.org> Co-authored-by: Gusted Co-committed-by: Gusted --- routers/api/v1/repo/collaborators.go | 14 +++++++++----- tests/integration/api_repo_collaborator_test.go | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go index 9ef1a92be4..f648c41adc 100644 --- a/routers/api/v1/repo/collaborators.go +++ b/routers/api/v1/repo/collaborators.go @@ -282,11 +282,6 @@ func GetRepoPermissions(ctx *context.APIContext) { // "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, ctx.Params(":collaborator")) if err != nil { if user_model.IsErrUserNotExist(err) { @@ -297,6 +292,15 @@ func GetRepoPermissions(ctx *context.APIContext) { return } + // Only allow the request in any of the following situations: + // - The user is the instance admin. + // - The user is the repository admin. + // - The user is querying the permissiosn of themselves. + if !ctx.IsUserSiteAdmin() && ctx.Doer.ID != collaborator.ID && !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 + } + permission, err := access_model.GetUserRepoPermission(ctx, ctx.Repo.Repository, collaborator) if err != nil { ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err) diff --git a/tests/integration/api_repo_collaborator_test.go b/tests/integration/api_repo_collaborator_test.go index 59cf85fef3..81d7a591f8 100644 --- a/tests/integration/api_repo_collaborator_test.go +++ b/tests/integration/api_repo_collaborator_test.go @@ -52,6 +52,20 @@ func TestAPIRepoCollaboratorPermission(t *testing.T) { DecodeJSON(t, resp, &repoPermission) assert.Equal(t, "read", repoPermission.Permission) + + t.Run("CollaboratorCanReadTheirPermission", func(t *testing.T) { + session := loginUser(t, user4.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository) + + req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/collaborators/%s/permission", repo2Owner.Name, repo2.Name, user4.Name). + AddTokenAuth(token) + resp := 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) {