Skip to content

Commit ef12b8d

Browse files
authored
Ensure that restricted users can access repos for which they are members (#17460) (#17464)
Backport #17460 There is a small bug in the way that repo access is checked in repoAssignment: Accessibility is checked by checking if the user has a marked access to the repository instead of checking if the user has any team granted access. This PR changes this permissions check to use HasAccess() which does the correct test. There is also a fix in the release api ListReleases where it should return draft releases if the user is a member of a team with write access to the releases. The PR also adds a testcase. Signed-off-by: Andrew Thornton <[email protected]>
1 parent dd1ba34 commit ef12b8d

File tree

4 files changed

+67
-4
lines changed

4 files changed

+67
-4
lines changed

integrations/org_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
package integrations
66

77
import (
8+
"fmt"
89
"net/http"
910
"strings"
1011
"testing"
1112

13+
api "code.gitea.io/gitea/modules/structs"
1214
"github.com/stretchr/testify/assert"
1315
)
1416

@@ -110,3 +112,64 @@ func TestPrivateOrg(t *testing.T) {
110112
req = NewRequest(t, "GET", "/privated_org/private_repo_on_private_org")
111113
session.MakeRequest(t, req, http.StatusOK)
112114
}
115+
116+
func TestOrgRestrictedUser(t *testing.T) {
117+
defer prepareTestEnv(t)()
118+
119+
// privated_org is a private org who has id 23
120+
orgName := "privated_org"
121+
122+
// public_repo_on_private_org is a public repo on privated_org
123+
repoName := "public_repo_on_private_org"
124+
125+
// user29 is a restricted user who is not a member of the organization
126+
restrictedUser := "user29"
127+
128+
// #17003 reports a bug whereby adding a restricted user to a read-only team doesn't work
129+
130+
// assert restrictedUser cannot see the org or the public repo
131+
restrictedSession := loginUser(t, restrictedUser)
132+
req := NewRequest(t, "GET", fmt.Sprintf("/%s", orgName))
133+
restrictedSession.MakeRequest(t, req, http.StatusNotFound)
134+
135+
req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s", orgName, repoName))
136+
restrictedSession.MakeRequest(t, req, http.StatusNotFound)
137+
138+
// Therefore create a read-only team
139+
adminSession := loginUser(t, "user1")
140+
token := getTokenForLoggedInUser(t, adminSession)
141+
142+
teamToCreate := &api.CreateTeamOption{
143+
Name: "codereader",
144+
Description: "Code Reader",
145+
IncludesAllRepositories: true,
146+
Permission: "read",
147+
Units: []string{"repo.code"},
148+
}
149+
150+
req = NewRequestWithJSON(t, "POST",
151+
fmt.Sprintf("/api/v1/orgs/%s/teams?token=%s", orgName, token), teamToCreate)
152+
153+
var apiTeam api.Team
154+
155+
resp := adminSession.MakeRequest(t, req, http.StatusCreated)
156+
DecodeJSON(t, resp, &apiTeam)
157+
checkTeamResponse(t, &apiTeam, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
158+
teamToCreate.Permission, teamToCreate.Units)
159+
checkTeamBean(t, apiTeam.ID, teamToCreate.Name, teamToCreate.Description, teamToCreate.IncludesAllRepositories,
160+
teamToCreate.Permission, teamToCreate.Units)
161+
//teamID := apiTeam.ID
162+
163+
// Now we need to add the restricted user to the team
164+
req = NewRequest(t, "PUT",
165+
fmt.Sprintf("/api/v1/teams/%d/members/%s?token=%s", apiTeam.ID, restrictedUser, token))
166+
_ = adminSession.MakeRequest(t, req, http.StatusNoContent)
167+
168+
// Now we need to check if the restrictedUser can access the repo
169+
req = NewRequest(t, "GET", fmt.Sprintf("/%s", orgName))
170+
restrictedSession.MakeRequest(t, req, http.StatusOK)
171+
172+
req = NewRequest(t, "GET", fmt.Sprintf("/%s/%s", orgName, repoName))
173+
restrictedSession.MakeRequest(t, req, http.StatusOK)
174+
175+
}

models/fixtures/repository.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@
568568
-
569569
id: 40
570570
owner_id: 23
571-
owner_name: limited_org
571+
owner_name: privated_org
572572
lower_name: public_repo_on_private_org
573573
name: public_repo_on_private_org
574574
is_private: false
@@ -581,7 +581,7 @@
581581
-
582582
id: 41
583583
owner_id: 23
584-
owner_name: limited_org
584+
owner_name: privated_org
585585
lower_name: private_repo_on_private_org
586586
name: private_repo_on_private_org
587587
is_private: true

modules/context/repo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ func repoAssignment(ctx *Context, repo *models.Repository) {
345345
}
346346

347347
// Check access.
348-
if ctx.Repo.Permission.AccessMode == models.AccessModeNone {
348+
if !ctx.Repo.Permission.HasAccess() {
349349
if ctx.Query("go-get") == "1" {
350350
EarlyResponseForGoGetMeta(ctx)
351351
return

routers/api/v1/repo/release.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func ListReleases(ctx *context.APIContext) {
115115

116116
opts := models.FindReleasesOptions{
117117
ListOptions: listOptions,
118-
IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite,
118+
IncludeDrafts: ctx.Repo.AccessMode >= models.AccessModeWrite || ctx.Repo.UnitAccessMode(models.UnitTypeReleases) >= models.AccessModeWrite,
119119
IncludeTags: false,
120120
IsDraft: ctx.QueryOptionalBool("draft"),
121121
IsPreRelease: ctx.QueryOptionalBool("pre-release"),

0 commit comments

Comments
 (0)