mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-12 22:10:25 +00:00
feat: implement fine-grained access tokens in /repositories/{id}
**Breaking**: accessing the `/repositories/{id}` API with a public-only
access token did not restrict read access to only public repositories.
As part of a consolidation of permission logic with repo-specific access
tokens, this access has not been restricted.
This commit is contained in:
parent
bbb7d52fc0
commit
b9be4b7648
2 changed files with 53 additions and 2 deletions
|
|
@ -599,9 +599,9 @@ func GetByID(ctx *context.APIContext) {
|
|||
return
|
||||
}
|
||||
|
||||
permission, err := access_model.GetUserRepoPermission(ctx, repo, ctx.Doer)
|
||||
permission, err := access_model.GetUserRepoPermissionWithReducer(ctx, repo, ctx.Doer, ctx.Reducer)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
|
||||
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermissionWithReducer", err)
|
||||
return
|
||||
} else if !permission.HasAccess() {
|
||||
ctx.NotFound()
|
||||
|
|
|
|||
|
|
@ -480,6 +480,57 @@ func TestAPIGetRepoByIDUnauthorized(t *testing.T) {
|
|||
MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
|
||||
func TestAPIGetRepoByIDAccessTokenResources(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
// Test targets:
|
||||
// id 1 - user2/repo1 - public repo
|
||||
// id 2 - user2/repo2 - private repo
|
||||
// id 16 - user2/repo16 - private repo
|
||||
testCase := func(t *testing.T, repoID int, token string, expectedStatus int) {
|
||||
req := NewRequest(t,
|
||||
"GET",
|
||||
fmt.Sprintf("/api/v1/repositories/%d", repoID)).
|
||||
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, 1, allToken, http.StatusOK) // public user2/repo1
|
||||
testCase(t, 2, allToken, http.StatusOK) // private user2/repo2
|
||||
testCase(t, 16, allToken, http.StatusOK) // private org3/repo3
|
||||
})
|
||||
|
||||
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, 1, publicOnlyToken, http.StatusOK) // public user2/repo1
|
||||
testCase(t, 2, publicOnlyToken, http.StatusNotFound) // private user2/repo2
|
||||
testCase(t, 16, publicOnlyToken, http.StatusNotFound) // private org3/repo3
|
||||
})
|
||||
|
||||
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{2},
|
||||
)
|
||||
|
||||
testCase(t, 1, repo2OnlyToken, http.StatusOK) // public user2/repo1, read-only outside of the auth'd repos
|
||||
testCase(t, 2, repo2OnlyToken, http.StatusOK) // private org3/repo3
|
||||
testCase(t, 16, repo2OnlyToken, http.StatusNotFound) // private user2/repo20, outside of fine-grain
|
||||
})
|
||||
}
|
||||
|
||||
func TestAPIRepoMigrate(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ctxUserID, userID int64
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue