mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Backport of #20873 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> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
		@@ -14,6 +14,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/models/packages"
 | 
			
		||||
	"code.gitea.io/gitea/models/unittest"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
@@ -79,6 +80,18 @@ func TestPackageGeneric(t *testing.T) {
 | 
			
		||||
		assert.Equal(t, int64(1), pvs[0].DownloadCount)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("RequireSignInView", func(t *testing.T) {
 | 
			
		||||
		defer PrintCurrentTest(t)()
 | 
			
		||||
 | 
			
		||||
		setting.Service.RequireSignInView = true
 | 
			
		||||
		defer func() {
 | 
			
		||||
			setting.Service.RequireSignInView = false
 | 
			
		||||
		}()
 | 
			
		||||
 | 
			
		||||
		req := NewRequest(t, "GET", url)
 | 
			
		||||
		MakeRequest(t, req, http.StatusUnauthorized)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("Delete", func(t *testing.T) {
 | 
			
		||||
		defer PrintCurrentTest(t)()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/models/perm"
 | 
			
		||||
	"code.gitea.io/gitea/models/unit"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	"code.gitea.io/gitea/modules/structs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -52,47 +53,11 @@ func packageAssignment(ctx *Context, errCb func(int, string, interface{})) {
 | 
			
		||||
		Owner: ctx.ContextUser,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
			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
 | 
			
		||||
		}
 | 
			
		||||
	var err error
 | 
			
		||||
	ctx.Package.AccessMode, err = determineAccessMode(ctx)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		errCb(http.StatusInternalServerError, "determineAccessMode", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	packageType := ctx.Params("type")
 | 
			
		||||
@@ -117,6 +82,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.
 | 
			
		||||
func PackageContexter() func(next http.Handler) http.Handler {
 | 
			
		||||
	return func(next http.Handler) http.Handler {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user