forked from NYANDEV/forgejo
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:
parent
d9bc6881ef
commit
0a9a86b943
2 changed files with 70 additions and 41 deletions
|
@ -14,6 +14,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"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
)
|
||||
|
@ -54,47 +55,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")
|
||||
|
@ -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.
|
||||
func PackageContexter(ctx gocontext.Context) func(next http.Handler) http.Handler {
|
||||
_, rnd := templates.HTMLRenderer(ctx)
|
||||
|
|
|
@ -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"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -126,6 +127,18 @@ func TestPackageGeneric(t *testing.T) {
|
|||
req := NewRequest(t, "GET", url+"/not.found")
|
||||
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) {
|
||||
|
|
Loading…
Reference in a new issue