aboutsummaryrefslogtreecommitdiffstats
path: root/modules/context
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2018-11-28 19:26:14 +0800
committerGitHub <noreply@github.com>2018-11-28 19:26:14 +0800
commiteabbddcd98717ef20d8475e819f403c50f4a9787 (patch)
treeefc525e7ec60d56d3bec72019febfa088a128b89 /modules/context
parent0222623be9fa4a56d870213f77b92139cefc2518 (diff)
downloadgitea-eabbddcd98717ef20d8475e819f403c50f4a9787.tar.gz
gitea-eabbddcd98717ef20d8475e819f403c50f4a9787.zip
Restrict permission check on repositories and fix some problems (#5314)
* fix units permission problems * fix some bugs and merge LoadUnits to repoAssignment * refactor permission struct and add some copyright heads * remove unused codes * fix routes units check * improve permission check * add unit tests for permission * fix typo * fix tests * fix some routes * fix api permission check * improve permission check * fix some permission check * fix tests * fix tests * improve some permission check * fix some permission check * refactor AccessLevel * fix bug * fix tests * fix tests * fix tests * fix AccessLevel * rename CanAccess * fix tests * fix comment * fix bug * add missing unit for test repos * fix bug * rename some functions * fix routes check
Diffstat (limited to 'modules/context')
-rw-r--r--modules/context/permission.go64
-rw-r--r--modules/context/repo.go123
2 files changed, 80 insertions, 107 deletions
diff --git a/modules/context/permission.go b/modules/context/permission.go
new file mode 100644
index 0000000000..70f8695300
--- /dev/null
+++ b/modules/context/permission.go
@@ -0,0 +1,64 @@
+// Copyright 2018 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package context
+
+import (
+ "code.gitea.io/gitea/models"
+ macaron "gopkg.in/macaron.v1"
+)
+
+// RequireRepoAdmin returns a macaron middleware for requiring repository admin permission
+func RequireRepoAdmin() macaron.Handler {
+ return func(ctx *Context) {
+ if !ctx.IsSigned || !ctx.Repo.IsAdmin() {
+ ctx.NotFound(ctx.Req.RequestURI, nil)
+ return
+ }
+ }
+}
+
+// RequireRepoWriter returns a macaron middleware for requiring repository write to the specify unitType
+func RequireRepoWriter(unitType models.UnitType) macaron.Handler {
+ return func(ctx *Context) {
+ if !ctx.Repo.CanWrite(unitType) {
+ ctx.NotFound(ctx.Req.RequestURI, nil)
+ return
+ }
+ }
+}
+
+// RequireRepoWriterOr returns a macaron middleware for requiring repository write to one of the unit permission
+func RequireRepoWriterOr(unitTypes ...models.UnitType) macaron.Handler {
+ return func(ctx *Context) {
+ for _, unitType := range unitTypes {
+ if ctx.Repo.CanWrite(unitType) {
+ return
+ }
+ }
+ ctx.NotFound(ctx.Req.RequestURI, nil)
+ }
+}
+
+// RequireRepoReader returns a macaron middleware for requiring repository read to the specify unitType
+func RequireRepoReader(unitType models.UnitType) macaron.Handler {
+ return func(ctx *Context) {
+ if !ctx.Repo.CanRead(unitType) {
+ ctx.NotFound(ctx.Req.RequestURI, nil)
+ return
+ }
+ }
+}
+
+// RequireRepoReaderOr returns a macaron middleware for requiring repository write to one of the unit permission
+func RequireRepoReaderOr(unitTypes ...models.UnitType) macaron.Handler {
+ return func(ctx *Context) {
+ for _, unitType := range unitTypes {
+ if ctx.Repo.CanRead(unitType) {
+ return
+ }
+ }
+ ctx.NotFound(ctx.Req.RequestURI, nil)
+ }
+}
diff --git a/modules/context/repo.go b/modules/context/repo.go
index be08bc4c77..55d607a28a 100644
--- a/modules/context/repo.go
+++ b/modules/context/repo.go
@@ -32,7 +32,7 @@ type PullRequest struct {
// Repository contains information to operate a repository
type Repository struct {
- AccessMode models.AccessMode
+ models.Permission
IsWatching bool
IsViewBranch bool
IsViewTag bool
@@ -54,34 +54,14 @@ type Repository struct {
PullRequest *PullRequest
}
-// IsOwner returns true if current user is the owner of repository.
-func (r *Repository) IsOwner() bool {
- return r.AccessMode >= models.AccessModeOwner
-}
-
-// IsAdmin returns true if current user has admin or higher access of repository.
-func (r *Repository) IsAdmin() bool {
- return r.AccessMode >= models.AccessModeAdmin
-}
-
-// IsWriter returns true if current user has write or higher access of repository.
-func (r *Repository) IsWriter() bool {
- return r.AccessMode >= models.AccessModeWrite
-}
-
-// HasAccess returns true if the current user has at least read access for this repository
-func (r *Repository) HasAccess() bool {
- return r.AccessMode >= models.AccessModeRead
-}
-
// CanEnableEditor returns true if repository is editable and user has proper access level.
func (r *Repository) CanEnableEditor() bool {
- return r.Repository.CanEnableEditor() && r.IsViewBranch && r.IsWriter()
+ return r.Permission.CanWrite(models.UnitTypeCode) && r.Repository.CanEnableEditor() && r.IsViewBranch
}
// CanCreateBranch returns true if repository is editable and user has proper access level.
func (r *Repository) CanCreateBranch() bool {
- return r.Repository.CanCreateBranch() && r.IsWriter()
+ return r.Permission.CanWrite(models.UnitTypeCode) && r.Repository.CanCreateBranch()
}
// CanCommitToBranch returns true if repository is editable and user has proper access level
@@ -101,12 +81,12 @@ func (r *Repository) CanUseTimetracker(issue *models.Issue, user *models.User) b
// 2. Is the user a contributor, admin, poster or assignee and do the repository policies require this?
isAssigned, _ := models.IsUserAssignedToIssue(issue, user)
return r.Repository.IsTimetrackerEnabled() && (!r.Repository.AllowOnlyContributorsToTrackTime() ||
- r.IsWriter() || issue.IsPoster(user.ID) || isAssigned)
+ r.Permission.CanWrite(models.UnitTypeIssues) || issue.IsPoster(user.ID) || isAssigned)
}
// CanCreateIssueDependencies returns whether or not a user can create dependencies.
func (r *Repository) CanCreateIssueDependencies(user *models.User) bool {
- return r.Repository.IsDependenciesEnabled() && r.IsWriter()
+ return r.Permission.CanWrite(models.UnitTypeIssues) && r.Repository.IsDependenciesEnabled()
}
// GetCommitsCount returns cached commit count for current view
@@ -221,24 +201,15 @@ func RedirectToRepo(ctx *Context, redirectRepoID int64) {
}
func repoAssignment(ctx *Context, repo *models.Repository) {
- // Admin has super access.
- if ctx.IsSigned && ctx.User.IsAdmin {
- ctx.Repo.AccessMode = models.AccessModeOwner
- } else {
- var userID int64
- if ctx.User != nil {
- userID = ctx.User.ID
- }
- mode, err := models.AccessLevel(userID, repo)
- if err != nil {
- ctx.ServerError("AccessLevel", err)
- return
- }
- ctx.Repo.AccessMode = mode
+ var err error
+ ctx.Repo.Permission, err = models.GetUserRepoPermission(repo, ctx.User)
+ if err != nil {
+ ctx.ServerError("GetUserRepoPermission", err)
+ return
}
// Check access.
- if ctx.Repo.AccessMode == models.AccessModeNone {
+ if ctx.Repo.Permission.AccessMode == models.AccessModeNone {
if ctx.Query("go-get") == "1" {
EarlyResponseForGoGetMeta(ctx)
return
@@ -247,6 +218,7 @@ func repoAssignment(ctx *Context, repo *models.Repository) {
return
}
ctx.Data["HasAccess"] = true
+ ctx.Data["Permission"] = &ctx.Repo.Permission
if repo.IsMirror {
var err error
@@ -281,10 +253,6 @@ func RepoIDAssignment() macaron.Handler {
return
}
- if err = repo.GetOwner(); err != nil {
- ctx.ServerError("GetOwner", err)
- return
- }
repoAssignment(ctx, repo)
}
}
@@ -381,7 +349,9 @@ func RepoAssignment() macaron.Handler {
ctx.Data["Owner"] = ctx.Repo.Repository.Owner
ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner()
ctx.Data["IsRepositoryAdmin"] = ctx.Repo.IsAdmin()
- ctx.Data["IsRepositoryWriter"] = ctx.Repo.IsWriter()
+ ctx.Data["CanWriteCode"] = ctx.Repo.CanWrite(models.UnitTypeCode)
+ ctx.Data["CanWriteIssues"] = ctx.Repo.CanWrite(models.UnitTypeIssues)
+ ctx.Data["CanWritePulls"] = ctx.Repo.CanWrite(models.UnitTypePullRequests)
if ctx.Data["CanSignedUserFork"], err = ctx.Repo.Repository.CanUserFork(ctx.User); err != nil {
ctx.ServerError("CanUserFork", err)
@@ -435,7 +405,7 @@ func RepoAssignment() macaron.Handler {
}
// People who have push access or have forked repository can propose a new pull request.
- if ctx.Repo.IsWriter() || (ctx.IsSigned && ctx.User.HasForkedRepo(ctx.Repo.Repository.ID)) {
+ if ctx.Repo.CanWrite(models.UnitTypeCode) || (ctx.IsSigned && ctx.User.HasForkedRepo(ctx.Repo.Repository.ID)) {
// Pull request is allowed if this is a fork repository
// and base repository accepts pull requests.
if repo.BaseRepo != nil && repo.BaseRepo.AllowsPulls() {
@@ -453,9 +423,6 @@ func RepoAssignment() macaron.Handler {
ctx.Repo.PullRequest.HeadInfo = ctx.Repo.BranchName
}
}
-
- // Reset repo units as otherwise user specific units wont be loaded later
- ctx.Repo.Repository.Units = nil
}
ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
@@ -661,64 +628,6 @@ func RepoRefByType(refType RepoRefType) macaron.Handler {
}
}
-// RequireRepoAdmin returns a macaron middleware for requiring repository admin permission
-func RequireRepoAdmin() macaron.Handler {
- return func(ctx *Context) {
- if !ctx.IsSigned || (!ctx.Repo.IsAdmin() && !ctx.User.IsAdmin) {
- ctx.NotFound(ctx.Req.RequestURI, nil)
- return
- }
- }
-}
-
-// RequireRepoWriter returns a macaron middleware for requiring repository write permission
-func RequireRepoWriter() macaron.Handler {
- return func(ctx *Context) {
- if !ctx.IsSigned || (!ctx.Repo.IsWriter() && !ctx.User.IsAdmin) {
- ctx.NotFound(ctx.Req.RequestURI, nil)
- return
- }
- }
-}
-
-// LoadRepoUnits loads repsitory's units, it should be called after repository and user loaded
-func LoadRepoUnits() macaron.Handler {
- return func(ctx *Context) {
- var isAdmin bool
- if ctx.User != nil && ctx.User.IsAdmin {
- isAdmin = true
- }
-
- var userID int64
- if ctx.User != nil {
- userID = ctx.User.ID
- }
- err := ctx.Repo.Repository.LoadUnitsByUserID(userID, isAdmin)
- if err != nil {
- ctx.ServerError("LoadUnitsByUserID", err)
- return
- }
- }
-}
-
-// CheckUnit will check whether unit type is enabled
-func CheckUnit(unitType models.UnitType) macaron.Handler {
- return func(ctx *Context) {
- if !ctx.Repo.Repository.UnitEnabled(unitType) {
- ctx.NotFound("CheckUnit", fmt.Errorf("%s: %v", ctx.Tr("units.error.unit_not_allowed"), unitType))
- }
- }
-}
-
-// CheckAnyUnit will check whether any of the unit types are enabled
-func CheckAnyUnit(unitTypes ...models.UnitType) macaron.Handler {
- return func(ctx *Context) {
- if !ctx.Repo.Repository.AnyUnitEnabled(unitTypes...) {
- ctx.NotFound("CheckAnyUnit", fmt.Errorf("%s: %v", ctx.Tr("units.error.unit_not_allowed"), unitTypes))
- }
- }
-}
-
// GitHookService checks if repository Git hooks service has been enabled.
func GitHookService() macaron.Handler {
return func(ctx *Context) {