mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-28 09:44:53 -04:00
feat: implement fine-grained access tokens in /repos/{owner}/{repo}/pulls & /repos/{owner}/{repo}/compare/{basehead} APIs
As these APIs only work on forks, and it's not possible to change the visibility of a fork from its parent, only testing the API access pattern against the head is sufficient. Also it is not a breaking change due to checkTokenPublicOnly middleware already enforcing this for public-only scopes, and the lack of ability to change a fork's visibility.
This commit is contained in:
parent
94dd94c2c0
commit
f9a2167105
2 changed files with 51 additions and 4 deletions
|
|
@ -1150,10 +1150,10 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
|
|||
}
|
||||
|
||||
// user should have permission to read baseRepo's codes and pulls, NOT headRepo's
|
||||
permBase, err := access_model.GetUserRepoPermission(ctx, baseRepo, ctx.Doer)
|
||||
permBase, err := access_model.GetUserRepoPermissionWithReducer(ctx, baseRepo, ctx.Doer, ctx.Reducer)
|
||||
if err != nil {
|
||||
headGitRepo.Close()
|
||||
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
|
||||
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermissionWithReducer", err)
|
||||
return nil, nil, nil, "", ""
|
||||
}
|
||||
if !permBase.CanReadIssuesOrPulls(true) || !permBase.CanRead(unit.TypeCode) {
|
||||
|
|
@ -1169,10 +1169,10 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
|
|||
}
|
||||
|
||||
// user should have permission to read headrepo's codes
|
||||
permHead, err := access_model.GetUserRepoPermission(ctx, headRepo, ctx.Doer)
|
||||
permHead, err := access_model.GetUserRepoPermissionWithReducer(ctx, headRepo, ctx.Doer, ctx.Reducer)
|
||||
if err != nil {
|
||||
headGitRepo.Close()
|
||||
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
|
||||
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermissionWithReducer", err)
|
||||
return nil, nil, nil, "", ""
|
||||
}
|
||||
if !permHead.CanRead(unit.TypeCode) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import (
|
|||
user_model "forgejo.org/models/user"
|
||||
"forgejo.org/modules/git"
|
||||
api "forgejo.org/modules/structs"
|
||||
"forgejo.org/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
|
@ -269,3 +270,49 @@ func testAPICompareCommits(t *testing.T, objectFormat git.ObjectFormat) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAPICompareCommitsAccessTokenResources(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
// Using the compare API, will be testing that the base repo's security checks implement fine-grained access
|
||||
// controls (and baselines with all and public-only).
|
||||
testCase := func(t *testing.T, repo, token string, expectedStatus int) {
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/compare/master...master", repo)).AddTokenAuth(token)
|
||||
MakeRequest(t, req, expectedStatus)
|
||||
}
|
||||
|
||||
t.Run("all access token", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
allToken := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository)
|
||||
|
||||
testCase(t, "user2/repo1", allToken, http.StatusOK) // public user2/repo1
|
||||
testCase(t, "org3/repo3", allToken, http.StatusOK) // private org3/repo3
|
||||
testCase(t, "user2/repo20", allToken, http.StatusOK) // private user2/repo20
|
||||
})
|
||||
|
||||
t.Run("public-only access token", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
publicOnlyToken := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopePublicOnly, auth_model.AccessTokenScopeReadRepository)
|
||||
|
||||
testCase(t, "user2/repo1", publicOnlyToken, http.StatusOK) // public user2/repo1
|
||||
testCase(t, "org3/repo3", publicOnlyToken, http.StatusNotFound) // private org3/repo3
|
||||
testCase(t, "user2/repo20", publicOnlyToken, http.StatusNotFound) // private user2/repo20
|
||||
})
|
||||
|
||||
t.Run("specific repo access token", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
repo2OnlyToken := createFineGrainedRepoAccessToken(t, "user2",
|
||||
[]auth_model.AccessTokenScope{auth_model.AccessTokenScopeReadRepository},
|
||||
[]int64{3},
|
||||
)
|
||||
|
||||
testCase(t, "user2/repo1", repo2OnlyToken, http.StatusOK) // public user2/repo1
|
||||
testCase(t, "org3/repo3", repo2OnlyToken, http.StatusOK) // private org3/repo3
|
||||
testCase(t, "user2/repo20", repo2OnlyToken, http.StatusNotFound) // private user2/repo20, outside of fine-grain
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue