mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Fix access check for org-level project (#26182)
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.
This commit is contained in:
		@@ -280,3 +280,9 @@
 | 
				
			|||||||
  team_id: 20
 | 
					  team_id: 20
 | 
				
			||||||
  type: 9 # package
 | 
					  type: 9 # package
 | 
				
			||||||
  access_mode: 2
 | 
					  access_mode: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					  id: 48
 | 
				
			||||||
 | 
					  team_id: 2
 | 
				
			||||||
 | 
					  type: 8
 | 
				
			||||||
 | 
					  access_mode: 2
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -254,9 +254,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) {
 | 
							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)
 | 
									ctx.NotFound(unitType.String(), nil)
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -832,7 +833,7 @@ func registerRoutes(m *web.Route) {
 | 
				
			|||||||
			m.Group("", func() {
 | 
								m.Group("", func() {
 | 
				
			||||||
				m.Get("", org.Projects)
 | 
									m.Get("", org.Projects)
 | 
				
			||||||
				m.Get("/{id}", org.ViewProject)
 | 
									m.Get("/{id}", org.ViewProject)
 | 
				
			||||||
			}, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead))
 | 
								}, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead, true))
 | 
				
			||||||
			m.Group("", func() { //nolint:dupl
 | 
								m.Group("", func() { //nolint:dupl
 | 
				
			||||||
				m.Get("/new", org.RenderNewProject)
 | 
									m.Get("/new", org.RenderNewProject)
 | 
				
			||||||
				m.Post("/new", web.Bind(forms.CreateProjectForm{}), org.NewProjectPost)
 | 
									m.Post("/new", web.Bind(forms.CreateProjectForm{}), org.NewProjectPost)
 | 
				
			||||||
@@ -853,17 +854,17 @@ func registerRoutes(m *web.Route) {
 | 
				
			|||||||
						m.Post("/move", org.MoveIssues)
 | 
											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 {
 | 
									if ctx.ContextUser.IsIndividual() && ctx.ContextUser.ID != ctx.Doer.ID {
 | 
				
			||||||
					ctx.NotFound("NewProject", nil)
 | 
										ctx.NotFound("NewProject", nil)
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		}, repo.MustEnableProjects)
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		m.Group("", func() {
 | 
							m.Group("", func() {
 | 
				
			||||||
			m.Get("/code", user.CodeSearch)
 | 
								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)
 | 
						}, ignSignIn, context_service.UserAssignmentWeb(), context.OrgAssignment()) // for "/{username}/-" (packages, projects, code)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ***** Release Attachment Download without Signin
 | 
						// ***** Release Attachment Download without Signin
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										61
									
								
								tests/integration/org_project_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								tests/integration/org_project_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user