]> source.dussan.org Git - gitea.git/commitdiff
Fix access check for org-level project (#26182) (#26223)
authorGiteabot <teabot@gitea.io>
Sat, 29 Jul 2023 18:50:58 +0000 (02:50 +0800)
committerGitHub <noreply@github.com>
Sat, 29 Jul 2023 18:50:58 +0000 (18:50 +0000)
Backport #26182 by @Zettat123

Fix #25934

Add `ignoreGlobal` parameter to `reqUnitAccess` and only check global
disabled units when `ignoreGlobal` is true. So the org-level projects
and user-level projects won't be affected by global disabled
`repo.projects` unit.

Co-authored-by: Zettat123 <zettat123@gmail.com>
models/fixtures/team_unit.yml
routers/web/web.go
tests/integration/org_project_test.go [new file with mode: 0644]

index 5d2ba2fb6cbd77a1585a701f7c9c18d22091edb3..c5531aa57af52b0b9f016aebc4d12e18493315a5 100644 (file)
   team_id: 20
   type: 9 # package
   access_mode: 2
+
+-
+  id: 48
+  team_id: 2
+  type: 8
+  access_mode: 2
index 458cf0458c6a07460a4d9d8143dd8bdfc2bff72a..4ef640764bc9d7832f84184dd2748e74795ffdc4 100644 (file)
@@ -262,9 +262,10 @@ func registerRoutes(m *web.Route) {
                }
        }
 
-       reqUnitAccess := func(unitType unit.Type, accessMode perm.AccessMode) func(ctx *context.Context) {
+       reqUnitAccess := func(unitType unit.Type, accessMode perm.AccessMode, ignoreGlobal bool) func(ctx *context.Context) {
                return func(ctx *context.Context) {
-                       if unitType.UnitGlobalDisabled() {
+                       // only check global disabled units when ignoreGlobal is false
+                       if !ignoreGlobal && unitType.UnitGlobalDisabled() {
                                ctx.NotFound(unitType.String(), nil)
                                return
                        }
@@ -828,7 +829,7 @@ func registerRoutes(m *web.Route) {
                        m.Group("", func() {
                                m.Get("", org.Projects)
                                m.Get("/{id}", org.ViewProject)
-                       }, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead))
+                       }, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead, true))
                        m.Group("", func() { //nolint:dupl
                                m.Get("/new", org.RenderNewProject)
                                m.Post("/new", web.Bind(forms.CreateProjectForm{}), org.NewProjectPost)
@@ -849,17 +850,17 @@ func registerRoutes(m *web.Route) {
                                                m.Post("/move", org.MoveIssues)
                                        })
                                })
-                       }, reqSignIn, reqUnitAccess(unit.TypeProjects, perm.AccessModeWrite), func(ctx *context.Context) {
+                       }, reqSignIn, reqUnitAccess(unit.TypeProjects, perm.AccessModeWrite, true), func(ctx *context.Context) {
                                if ctx.ContextUser.IsIndividual() && ctx.ContextUser.ID != ctx.Doer.ID {
                                        ctx.NotFound("NewProject", nil)
                                        return
                                }
                        })
-               }, repo.MustEnableProjects)
+               })
 
                m.Group("", func() {
                        m.Get("/code", user.CodeSearch)
-               }, reqUnitAccess(unit.TypeCode, perm.AccessModeRead))
+               }, reqUnitAccess(unit.TypeCode, perm.AccessModeRead, false))
        }, ignSignIn, context_service.UserAssignmentWeb(), context.OrgAssignment()) // for "/{username}/-" (packages, projects, code)
 
        // ***** Release Attachment Download without Signin
diff --git a/tests/integration/org_project_test.go b/tests/integration/org_project_test.go
new file mode 100644 (file)
index 0000000..4ae94b4
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+       "net/http"
+       "testing"
+
+       unit_model "code.gitea.io/gitea/models/unit"
+       "code.gitea.io/gitea/tests"
+)
+
+func TestOrgProjectAccess(t *testing.T) {
+       defer tests.PrepareTestEnv(t)()
+
+       // disable repo project unit
+       unit_model.DisabledRepoUnits = []unit_model.Type{unit_model.TypeProjects}
+
+       // repo project, 404
+       req := NewRequest(t, "GET", "/user2/repo1/projects")
+       MakeRequest(t, req, http.StatusNotFound)
+
+       // user project, 200
+       req = NewRequest(t, "GET", "/user2/-/projects")
+       MakeRequest(t, req, http.StatusOK)
+
+       // org project, 200
+       req = NewRequest(t, "GET", "/user3/-/projects")
+       MakeRequest(t, req, http.StatusOK)
+
+       // change the org's visibility to private
+       session := loginUser(t, "user2")
+       req = NewRequestWithValues(t, "POST", "/org/user3/settings", map[string]string{
+               "_csrf":      GetCSRF(t, session, "/user3/-/projects"),
+               "name":       "user3",
+               "visibility": "2",
+       })
+       session.MakeRequest(t, req, http.StatusSeeOther)
+
+       // user4 can still access the org's project because its team(team1) has the permission
+       session = loginUser(t, "user4")
+       req = NewRequest(t, "GET", "/user3/-/projects")
+       session.MakeRequest(t, req, http.StatusOK)
+
+       // disable team1's project unit
+       session = loginUser(t, "user2")
+       req = NewRequestWithValues(t, "POST", "/org/user3/teams/team1/edit", map[string]string{
+               "_csrf":       GetCSRF(t, session, "/user3/-/projects"),
+               "team_name":   "team1",
+               "repo_access": "specific",
+               "permission":  "read",
+               "unit_8":      "0",
+       })
+       session.MakeRequest(t, req, http.StatusSeeOther)
+
+       // user4 can no longer access the org's project
+       session = loginUser(t, "user4")
+       req = NewRequest(t, "GET", "/user3/-/projects")
+       session.MakeRequest(t, req, http.StatusNotFound)
+}