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/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,48 +55,12 @@ func packageAssignment(ctx *Context, errCb func(int, string, interface{})) {
|
||||||
Owner: ctx.ContextUser,
|
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
|
var err error
|
||||||
ctx.Package.AccessMode, err = org.GetOrgUserMaxAuthorizeLevel(ctx.Doer.ID)
|
ctx.Package.AccessMode, err = determineAccessMode(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errCb(http.StatusInternalServerError, "GetOrgUserMaxAuthorizeLevel", err)
|
errCb(http.StatusInternalServerError, "determineAccessMode", err)
|
||||||
return
|
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")
|
||||||
name := ctx.Params("name")
|
name := ctx.Params("name")
|
||||||
|
@ -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 a new issue