mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Respect REQUIRE_SIGNIN_VIEW for packages (#20873)
				
					
				
			Fix #20863 When REQUIRE_SIGNIN_VIEW = true, even with public repositories, you can only see them after you login. The packages should not be accessed without login. Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
		| @@ -14,6 +14,7 @@ import ( | |||||||
| 	"code.gitea.io/gitea/models/perm" | 	"code.gitea.io/gitea/models/perm" | ||||||
| 	"code.gitea.io/gitea/models/unit" | 	"code.gitea.io/gitea/models/unit" | ||||||
| 	user_model "code.gitea.io/gitea/models/user" | 	user_model "code.gitea.io/gitea/models/user" | ||||||
|  | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/modules/structs" | 	"code.gitea.io/gitea/modules/structs" | ||||||
| 	"code.gitea.io/gitea/modules/templates" | 	"code.gitea.io/gitea/modules/templates" | ||||||
| ) | ) | ||||||
| @@ -54,47 +55,11 @@ func packageAssignment(ctx *Context, errCb func(int, string, interface{})) { | |||||||
| 		Owner: ctx.ContextUser, | 		Owner: ctx.ContextUser, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if ctx.Package.Owner.IsOrganization() { | 	var err error | ||||||
| 		org := organization.OrgFromUser(ctx.Package.Owner) | 	ctx.Package.AccessMode, err = determineAccessMode(ctx) | ||||||
|  | 	if err != nil { | ||||||
| 		// 1. Get user max authorize level for the org (may be none, if user is not member of the org) | 		errCb(http.StatusInternalServerError, "determineAccessMode", err) | ||||||
| 		if ctx.Doer != nil { | 		return | ||||||
| 			var err error |  | ||||||
| 			ctx.Package.AccessMode, err = org.GetOrgUserMaxAuthorizeLevel(ctx.Doer.ID) |  | ||||||
| 			if err != nil { |  | ||||||
| 				errCb(http.StatusInternalServerError, "GetOrgUserMaxAuthorizeLevel", err) |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 			// If access mode is less than write check every team for more permissions |  | ||||||
| 			if ctx.Package.AccessMode < perm.AccessModeWrite { |  | ||||||
| 				teams, err := organization.GetUserOrgTeams(ctx, org.ID, ctx.Doer.ID) |  | ||||||
| 				if err != nil { |  | ||||||
| 					errCb(http.StatusInternalServerError, "GetUserOrgTeams", err) |  | ||||||
| 					return |  | ||||||
| 				} |  | ||||||
| 				for _, t := range teams { |  | ||||||
| 					perm := t.UnitAccessModeCtx(ctx, unit.TypePackages) |  | ||||||
| 					if ctx.Package.AccessMode < perm { |  | ||||||
| 						ctx.Package.AccessMode = perm |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		// 2. If authorize level is none, check if org is visible to user |  | ||||||
| 		if ctx.Package.AccessMode == perm.AccessModeNone && organization.HasOrgOrUserVisible(ctx, ctx.Package.Owner, ctx.Doer) { |  | ||||||
| 			ctx.Package.AccessMode = perm.AccessModeRead |  | ||||||
| 		} |  | ||||||
| 	} else { |  | ||||||
| 		if ctx.Doer != nil && !ctx.Doer.IsGhost() { |  | ||||||
| 			// 1. Check if user is package owner |  | ||||||
| 			if ctx.Doer.ID == ctx.Package.Owner.ID { |  | ||||||
| 				ctx.Package.AccessMode = perm.AccessModeOwner |  | ||||||
| 			} else if ctx.Package.Owner.Visibility == structs.VisibleTypePublic || ctx.Package.Owner.Visibility == structs.VisibleTypeLimited { // 2. Check if package owner is public or limited |  | ||||||
| 				ctx.Package.AccessMode = perm.AccessModeRead |  | ||||||
| 			} |  | ||||||
| 		} else if ctx.Package.Owner.Visibility == structs.VisibleTypePublic { // 3. Check if package owner is public |  | ||||||
| 			ctx.Package.AccessMode = perm.AccessModeRead |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	packageType := ctx.Params("type") | 	packageType := ctx.Params("type") | ||||||
| @@ -119,6 +84,57 @@ func packageAssignment(ctx *Context, errCb func(int, string, interface{})) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func determineAccessMode(ctx *Context) (perm.AccessMode, error) { | ||||||
|  | 	accessMode := perm.AccessModeNone | ||||||
|  |  | ||||||
|  | 	if setting.Service.RequireSignInView && ctx.Doer == nil { | ||||||
|  | 		return accessMode, nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if ctx.Package.Owner.IsOrganization() { | ||||||
|  | 		org := organization.OrgFromUser(ctx.Package.Owner) | ||||||
|  |  | ||||||
|  | 		// 1. Get user max authorize level for the org (may be none, if user is not member of the org) | ||||||
|  | 		if ctx.Doer != nil { | ||||||
|  | 			var err error | ||||||
|  | 			accessMode, err = org.GetOrgUserMaxAuthorizeLevel(ctx.Doer.ID) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return accessMode, err | ||||||
|  | 			} | ||||||
|  | 			// If access mode is less than write check every team for more permissions | ||||||
|  | 			if accessMode < perm.AccessModeWrite { | ||||||
|  | 				teams, err := organization.GetUserOrgTeams(ctx, org.ID, ctx.Doer.ID) | ||||||
|  | 				if err != nil { | ||||||
|  | 					return accessMode, err | ||||||
|  | 				} | ||||||
|  | 				for _, t := range teams { | ||||||
|  | 					perm := t.UnitAccessModeCtx(ctx, unit.TypePackages) | ||||||
|  | 					if accessMode < perm { | ||||||
|  | 						accessMode = perm | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		// 2. If authorize level is none, check if org is visible to user | ||||||
|  | 		if accessMode == perm.AccessModeNone && organization.HasOrgOrUserVisible(ctx, ctx.Package.Owner, ctx.Doer) { | ||||||
|  | 			accessMode = perm.AccessModeRead | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		if ctx.Doer != nil && !ctx.Doer.IsGhost() { | ||||||
|  | 			// 1. Check if user is package owner | ||||||
|  | 			if ctx.Doer.ID == ctx.Package.Owner.ID { | ||||||
|  | 				accessMode = perm.AccessModeOwner | ||||||
|  | 			} else if ctx.Package.Owner.Visibility == structs.VisibleTypePublic || ctx.Package.Owner.Visibility == structs.VisibleTypeLimited { // 2. Check if package owner is public or limited | ||||||
|  | 				accessMode = perm.AccessModeRead | ||||||
|  | 			} | ||||||
|  | 		} else if ctx.Package.Owner.Visibility == structs.VisibleTypePublic { // 3. Check if package owner is public | ||||||
|  | 			accessMode = perm.AccessModeRead | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return accessMode, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // PackageContexter initializes a package context for a request. | // PackageContexter initializes a package context for a request. | ||||||
| func PackageContexter(ctx gocontext.Context) func(next http.Handler) http.Handler { | func PackageContexter(ctx gocontext.Context) func(next http.Handler) http.Handler { | ||||||
| 	_, rnd := templates.HTMLRenderer(ctx) | 	_, rnd := templates.HTMLRenderer(ctx) | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ import ( | |||||||
| 	"code.gitea.io/gitea/models/packages" | 	"code.gitea.io/gitea/models/packages" | ||||||
| 	"code.gitea.io/gitea/models/unittest" | 	"code.gitea.io/gitea/models/unittest" | ||||||
| 	user_model "code.gitea.io/gitea/models/user" | 	user_model "code.gitea.io/gitea/models/user" | ||||||
|  | 	"code.gitea.io/gitea/modules/setting" | ||||||
| 	"code.gitea.io/gitea/tests" | 	"code.gitea.io/gitea/tests" | ||||||
|  |  | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
| @@ -126,6 +127,18 @@ func TestPackageGeneric(t *testing.T) { | |||||||
| 			req := NewRequest(t, "GET", url+"/not.found") | 			req := NewRequest(t, "GET", url+"/not.found") | ||||||
| 			MakeRequest(t, req, http.StatusNotFound) | 			MakeRequest(t, req, http.StatusNotFound) | ||||||
| 		}) | 		}) | ||||||
|  |  | ||||||
|  | 		t.Run("RequireSignInView", func(t *testing.T) { | ||||||
|  | 			defer tests.PrintCurrentTest(t)() | ||||||
|  |  | ||||||
|  | 			setting.Service.RequireSignInView = true | ||||||
|  | 			defer func() { | ||||||
|  | 				setting.Service.RequireSignInView = false | ||||||
|  | 			}() | ||||||
|  |  | ||||||
|  | 			req = NewRequest(t, "GET", url+"/dummy.bin") | ||||||
|  | 			MakeRequest(t, req, http.StatusUnauthorized) | ||||||
|  | 		}) | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	t.Run("Delete", func(t *testing.T) { | 	t.Run("Delete", func(t *testing.T) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user