diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 315b44ce6f..cc08133afe 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -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 } diff --git a/tests/integration/api_team_test.go b/tests/integration/api_team_test.go index 2d16ea2b95..9413406b42 100644 --- a/tests/integration/api_team_test.go +++ b/tests/integration/api_team_test.go @@ -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) + }) + }) +} diff --git a/tests/integration/fixtures/TestAPIGetTeamRepoAccessTokenResources/team.yml b/tests/integration/fixtures/TestAPIGetTeamRepoAccessTokenResources/team.yml new file mode 100644 index 0000000000..19b2a3bc29 --- /dev/null +++ b/tests/integration/fixtures/TestAPIGetTeamRepoAccessTokenResources/team.yml @@ -0,0 +1,4 @@ +- + id: 26 + org_id: 3 + includes_all_repositories: false diff --git a/tests/integration/fixtures/TestAPIGetTeamRepoAccessTokenResources/team_repo.yml b/tests/integration/fixtures/TestAPIGetTeamRepoAccessTokenResources/team_repo.yml new file mode 100644 index 0000000000..285514a4f2 --- /dev/null +++ b/tests/integration/fixtures/TestAPIGetTeamRepoAccessTokenResources/team_repo.yml @@ -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 diff --git a/tests/integration/fixtures/TestAPIGetTeamRepoAccessTokenResources/team_user.yml b/tests/integration/fixtures/TestAPIGetTeamRepoAccessTokenResources/team_user.yml new file mode 100644 index 0000000000..8fb6e84ca6 --- /dev/null +++ b/tests/integration/fixtures/TestAPIGetTeamRepoAccessTokenResources/team_user.yml @@ -0,0 +1,5 @@ +- + id: 30 + org_id: 3 + team_id: 26 + uid: 2