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
This commit is contained in:
parent
0222623be9
commit
eabbddcd98
80 changed files with 1360 additions and 774 deletions
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue