mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-12 22:10:25 +00:00
feat: implement fine-grained access tokens in /teams/{id}/repos/{org}/{repo}
**Breaking*: /teams/{id}/repos/{org}/{repo} previously allowed read
access to private repositories even if a "public-only" access token was
in-use. This has been restricted to only return public repositories in
this case.
This commit is contained in:
parent
c89504d573
commit
0c2ece0ae7
5 changed files with 108 additions and 2 deletions
|
|
@ -632,9 +632,13 @@ func GetTeamRepo(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, "GetTeamRepos", err)
|
||||
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermissionWithReducer", err)
|
||||
return
|
||||
}
|
||||
if !permission.HasAccess() {
|
||||
ctx.NotFound()
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -319,3 +319,81 @@ func TestAPIGetTeamRepo(t *testing.T) {
|
|||
AddTokenAuth(token5)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
|
||||
func TestAPIGetTeamRepoAccessTokenResources(t *testing.T) {
|
||||
defer unittest.OverrideFixtures("tests/integration/fixtures/TestAPIGetTeamRepoAccessTokenResources")()
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
// Test cases org3/repo21 (public), org3/repo3 (private), org3/repo5 (private) --
|
||||
// TestAPIGetTeamReposAccessTokenResources fixtures create a team w/ ID=26 that contains all three repos.
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
var repo api.Repository
|
||||
|
||||
t.Run("all access token", func(t *testing.T) {
|
||||
allToken := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadOrganization)
|
||||
|
||||
t.Run("allowed public repo21", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", "/api/v1/teams/26/repos/org3/repo21").AddTokenAuth(allToken)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &repo)
|
||||
assert.False(t, repo.Private)
|
||||
})
|
||||
t.Run("allowed private repo3", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", "/api/v1/teams/26/repos/org3/repo3").AddTokenAuth(allToken)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &repo)
|
||||
assert.True(t, repo.Private)
|
||||
})
|
||||
// org3/repo5 is a second repo used in fine-grain testing below, so we include it in other tests as a baseline
|
||||
t.Run("allowed private repo5", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", "/api/v1/teams/26/repos/org3/repo5").AddTokenAuth(allToken)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &repo)
|
||||
assert.True(t, repo.Private)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("public-only access token", func(t *testing.T) {
|
||||
publicOnlyToken := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopePublicOnly, auth_model.AccessTokenScopeReadOrganization)
|
||||
|
||||
t.Run("allowed public repo21", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", "/api/v1/teams/26/repos/org3/repo21").AddTokenAuth(publicOnlyToken)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &repo)
|
||||
assert.False(t, repo.Private)
|
||||
})
|
||||
t.Run("denied private repo3", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", "/api/v1/teams/26/repos/org3/repo3").AddTokenAuth(publicOnlyToken)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
})
|
||||
t.Run("denied private repo5", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", "/api/v1/teams/26/repos/org3/repo5").AddTokenAuth(publicOnlyToken)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("specific repo access token", func(t *testing.T) {
|
||||
repo2OnlyToken := createFineGrainedRepoAccessToken(t, "user2",
|
||||
[]auth_model.AccessTokenScope{auth_model.AccessTokenScopeReadOrganization},
|
||||
[]int64{3},
|
||||
)
|
||||
|
||||
t.Run("allowed public repo21", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", "/api/v1/teams/26/repos/org3/repo21").AddTokenAuth(repo2OnlyToken)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &repo)
|
||||
assert.False(t, repo.Private)
|
||||
})
|
||||
t.Run("allowed inside fine-grain repo3", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", "/api/v1/teams/26/repos/org3/repo3").AddTokenAuth(repo2OnlyToken)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
DecodeJSON(t, resp, &repo)
|
||||
assert.True(t, repo.Private)
|
||||
})
|
||||
t.Run("denied private outside fine-grain repo5", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", "/api/v1/teams/26/repos/org3/repo5").AddTokenAuth(repo2OnlyToken)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
-
|
||||
id: 26
|
||||
org_id: 3
|
||||
includes_all_repositories: false
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
-
|
||||
id: 20
|
||||
org_id: 3
|
||||
team_id: 26
|
||||
repo_id: 32 # org3/repo21 - public
|
||||
-
|
||||
id: 21
|
||||
org_id: 3
|
||||
team_id: 26
|
||||
repo_id: 3 # org3/repo3 - private
|
||||
-
|
||||
id: 22
|
||||
org_id: 3
|
||||
team_id: 26
|
||||
repo_id: 5 # org3/repo5 - private
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
-
|
||||
id: 30
|
||||
org_id: 3
|
||||
team_id: 26
|
||||
uid: 2
|
||||
Loading…
Add table
Add a link
Reference in a new issue