Browse Source

Updating context and fixing permission issues

The boolean flags in the repo context have been replaced with mode and two methods

Also, the permissions have been brought more in line with https://help.github.com/articles/permission-levels-for-an-organization-repository/ , Admin Team members are able to change settings of their repositories.
pull/959/head
Peter Smit 10 years ago
parent
commit
ed89b39984
  1. 4
      cmd/web.go
  2. 55
      modules/middleware/context.go
  3. 47
      modules/middleware/repo.go
  4. 2
      routers/api/v1/repo_file.go
  5. 14
      routers/repo/issue.go
  6. 10
      routers/repo/release.go
  7. 2
      routers/repo/repo.go
  8. 2
      templates/repo/header.tmpl
  9. 2
      templates/repo/sidebar.tmpl
  10. 2
      templates/repo/toolbar.tmpl

4
cmd/web.go

@ -319,7 +319,7 @@ func runWeb(ctx *cli.Context) {
m.Get("/template/*", dev.TemplatePreview) m.Get("/template/*", dev.TemplatePreview)
} }
reqTrueOwner := middleware.RequireTrueOwner() reqAdmin := middleware.RequireAdmin()
// Organization. // Organization.
m.Group("/org", func() { m.Group("/org", func() {
@ -394,7 +394,7 @@ func runWeb(ctx *cli.Context) {
m.Post("/:name", repo.GitHooksEditPost) m.Post("/:name", repo.GitHooksEditPost)
}, middleware.GitHookService()) }, middleware.GitHookService())
}) })
}, reqSignIn, middleware.RepoAssignment(true), reqTrueOwner) }, reqSignIn, middleware.RepoAssignment(true), reqAdmin)
m.Group("/:username/:reponame", func() { m.Group("/:username/:reponame", func() {
m.Get("/action/:action", repo.Action) m.Get("/action/:action", repo.Action)

55
modules/middleware/context.go

@ -38,29 +38,7 @@ type Context struct {
IsSigned bool IsSigned bool
IsBasicAuth bool IsBasicAuth bool
Repo struct { Repo RepoContext
IsOwner bool
IsTrueOwner bool
IsWatching bool
IsBranch bool
IsTag bool
IsCommit bool
IsAdmin bool // Current user is admin level.
HasAccess bool
Repository *models.Repository
Owner *models.User
Commit *git.Commit
Tag *git.Tag
GitRepo *git.Repository
BranchName string
TagName string
TreeName string
CommitId string
RepoLink string
CloneLink models.CloneLink
CommitsCount int
Mirror *models.Mirror
}
Org struct { Org struct {
IsOwner bool IsOwner bool
@ -73,6 +51,37 @@ type Context struct {
} }
} }
type RepoContext struct {
AccessMode models.AccessMode
IsWatching bool
IsBranch bool
IsTag bool
IsCommit bool
Repository *models.Repository
Owner *models.User
Commit *git.Commit
Tag *git.Tag
GitRepo *git.Repository
BranchName string
TagName string
TreeName string
CommitId string
RepoLink string
CloneLink models.CloneLink
CommitsCount int
Mirror *models.Mirror
}
// Return if the current user has write access for this repository
func (r RepoContext) IsOwner() bool {
return r.AccessMode >= models.ACCESS_MODE_WRITE
}
// Return if the current user has read access for this repository
func (r RepoContext) HasAccess() bool {
return r.AccessMode >= models.ACCESS_MODE_READ
}
// HasError returns true if error occurs in form validation. // HasError returns true if error occurs in form validation.
func (ctx *Context) HasApiError() bool { func (ctx *Context) HasApiError() bool {
hasErr, ok := ctx.Data["HasError"] hasErr, ok := ctx.Data["HasError"]

47
modules/middleware/repo.go

@ -58,24 +58,19 @@ func ApiRepoAssignment() macaron.Handler {
return return
} }
if ctx.IsSigned { mode, err := models.AccessLevel(ctx.User, repo)
mode, err := models.AccessLevel(ctx.User, repo) if err != nil {
if err != nil { ctx.JSON(500, &base.ApiJsonErr{"AccessLevel: " + err.Error(), base.DOC_URL})
ctx.JSON(500, &base.ApiJsonErr{"AccessLevel: " + err.Error(), base.DOC_URL}) return
return
}
ctx.Repo.IsOwner = mode >= models.ACCESS_MODE_WRITE
ctx.Repo.IsAdmin = mode >= models.ACCESS_MODE_READ
ctx.Repo.IsTrueOwner = mode >= models.ACCESS_MODE_OWNER
} }
ctx.Repo.AccessMode = mode
// Check access. // Check access.
if repo.IsPrivate && !ctx.Repo.IsOwner { if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE {
ctx.Error(404) ctx.Error(404)
return return
} }
ctx.Repo.HasAccess = true
ctx.Repo.Repository = repo ctx.Repo.Repository = repo
} }
@ -239,26 +234,18 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
return return
} }
if ctx.IsSigned { mode, err := models.AccessLevel(ctx.User, repo)
mode, err := models.AccessLevel(ctx.User, repo) if err != nil {
if err != nil { ctx.Handle(500, "AccessLevel", err)
ctx.Handle(500, "AccessLevel", err) return
return
}
ctx.Repo.IsOwner = mode >= models.ACCESS_MODE_WRITE
ctx.Repo.IsAdmin = mode >= models.ACCESS_MODE_READ
ctx.Repo.IsTrueOwner = mode >= models.ACCESS_MODE_OWNER
if !ctx.Repo.IsTrueOwner && ctx.Repo.Owner.IsOrganization() {
ctx.Repo.IsTrueOwner = ctx.Repo.Owner.IsOwnedBy(ctx.User.Id)
}
} }
ctx.Repo.AccessMode = mode
// Check access. // Check access.
if repo.IsPrivate && !ctx.Repo.IsOwner { if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE {
ctx.Handle(404, "no access right", err) ctx.Handle(404, "no access right", err)
return return
} }
ctx.Repo.HasAccess = true
ctx.Data["HasAccess"] = true ctx.Data["HasAccess"] = true
@ -306,8 +293,8 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
ctx.Data["Title"] = u.Name + "/" + repo.Name ctx.Data["Title"] = u.Name + "/" + repo.Name
ctx.Data["Repository"] = repo ctx.Data["Repository"] = repo
ctx.Data["Owner"] = ctx.Repo.Repository.Owner ctx.Data["Owner"] = ctx.Repo.Repository.Owner
ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner ctx.Data["IsRepositoryOwner"] = ctx.Repo.AccessMode >= models.ACCESS_MODE_WRITE
ctx.Data["IsRepositoryTrueOwner"] = ctx.Repo.IsTrueOwner ctx.Data["IsRepositoryAdmin"] = ctx.Repo.AccessMode >= models.ACCESS_MODE_ADMIN
ctx.Data["DisableSSH"] = setting.DisableSSH ctx.Data["DisableSSH"] = setting.DisableSSH
ctx.Repo.CloneLink, err = repo.CloneLink() ctx.Repo.CloneLink, err = repo.CloneLink()
@ -362,9 +349,9 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
} }
} }
func RequireTrueOwner() macaron.Handler { func RequireAdmin() macaron.Handler {
return func(ctx *Context) { return func(ctx *Context) {
if !ctx.Repo.IsTrueOwner && !ctx.Repo.IsAdmin { if ctx.Repo.AccessMode < models.ACCESS_MODE_ADMIN {
if !ctx.IsSigned { if !ctx.IsSigned {
ctx.SetCookie("redirect_to", "/"+url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl) ctx.SetCookie("redirect_to", "/"+url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl)
ctx.Redirect(setting.AppSubUrl + "/user/login") ctx.Redirect(setting.AppSubUrl + "/user/login")

2
routers/api/v1/repo_file.go

@ -12,7 +12,7 @@ import (
) )
func GetRepoRawFile(ctx *middleware.Context) { func GetRepoRawFile(ctx *middleware.Context) {
if ctx.Repo.Repository.IsPrivate && !ctx.Repo.HasAccess { if !ctx.Repo.HasAccess() {
ctx.Error(404) ctx.Error(404)
return return
} }

14
routers/repo/issue.go

@ -230,7 +230,7 @@ func CreateIssuePost(ctx *middleware.Context, form auth.CreateIssueForm) {
} }
// Only collaborators can assign. // Only collaborators can assign.
if !ctx.Repo.IsOwner { if !ctx.Repo.IsOwner() {
form.AssigneeId = 0 form.AssigneeId = 0
} }
issue := &models.Issue{ issue := &models.Issue{
@ -434,7 +434,7 @@ func ViewIssue(ctx *middleware.Context) {
ctx.Data["Title"] = issue.Name ctx.Data["Title"] = issue.Name
ctx.Data["Issue"] = issue ctx.Data["Issue"] = issue
ctx.Data["Comments"] = comments ctx.Data["Comments"] = comments
ctx.Data["IsIssueOwner"] = ctx.Repo.IsOwner || (ctx.IsSigned && issue.PosterId == ctx.User.Id) ctx.Data["IsIssueOwner"] = ctx.Repo.IsOwner() || (ctx.IsSigned && issue.PosterId == ctx.User.Id)
ctx.Data["IsRepoToolbarIssues"] = true ctx.Data["IsRepoToolbarIssues"] = true
ctx.Data["IsRepoToolbarIssuesList"] = false ctx.Data["IsRepoToolbarIssuesList"] = false
ctx.HTML(200, ISSUE_VIEW) ctx.HTML(200, ISSUE_VIEW)
@ -457,7 +457,7 @@ func UpdateIssue(ctx *middleware.Context, form auth.CreateIssueForm) {
return return
} }
if ctx.User.Id != issue.PosterId && !ctx.Repo.IsOwner { if ctx.User.Id != issue.PosterId && !ctx.Repo.IsOwner() {
ctx.Error(403) ctx.Error(403)
return return
} }
@ -484,7 +484,7 @@ func UpdateIssue(ctx *middleware.Context, form auth.CreateIssueForm) {
} }
func UpdateIssueLabel(ctx *middleware.Context) { func UpdateIssueLabel(ctx *middleware.Context) {
if !ctx.Repo.IsOwner { if !ctx.Repo.IsOwner() {
ctx.Error(403) ctx.Error(403)
return return
} }
@ -560,7 +560,7 @@ func UpdateIssueLabel(ctx *middleware.Context) {
} }
func UpdateIssueMilestone(ctx *middleware.Context) { func UpdateIssueMilestone(ctx *middleware.Context) {
if !ctx.Repo.IsOwner { if !ctx.Repo.IsOwner() {
ctx.Error(403) ctx.Error(403)
return return
} }
@ -606,7 +606,7 @@ func UpdateIssueMilestone(ctx *middleware.Context) {
} }
func UpdateAssignee(ctx *middleware.Context) { func UpdateAssignee(ctx *middleware.Context) {
if !ctx.Repo.IsOwner { if !ctx.Repo.IsOwner() {
ctx.Error(403) ctx.Error(403)
return return
} }
@ -752,7 +752,7 @@ func Comment(ctx *middleware.Context) {
// Check if issue owner changes the status of issue. // Check if issue owner changes the status of issue.
var newStatus string var newStatus string
if ctx.Repo.IsOwner || issue.PosterId == ctx.User.Id { if ctx.Repo.IsOwner() || issue.PosterId == ctx.User.Id {
newStatus = ctx.Query("change_status") newStatus = ctx.Query("change_status")
} }
if len(newStatus) > 0 { if len(newStatus) > 0 {

10
routers/repo/release.go

@ -41,7 +41,7 @@ func Releases(ctx *middleware.Context) {
tags := make([]*models.Release, len(rawTags)) tags := make([]*models.Release, len(rawTags))
for i, rawTag := range rawTags { for i, rawTag := range rawTags {
for j, rel := range rels { for j, rel := range rels {
if rel == nil || (rel.IsDraft && !ctx.Repo.IsOwner) { if rel == nil || (rel.IsDraft && !ctx.Repo.IsOwner()) {
continue continue
} }
if rel.TagName == rawTag { if rel.TagName == rawTag {
@ -140,7 +140,7 @@ func Releases(ctx *middleware.Context) {
} }
func NewRelease(ctx *middleware.Context) { func NewRelease(ctx *middleware.Context) {
if !ctx.Repo.IsOwner { if !ctx.Repo.IsOwner() {
ctx.Handle(403, "release.ReleasesNew", nil) ctx.Handle(403, "release.ReleasesNew", nil)
return return
} }
@ -153,7 +153,7 @@ func NewRelease(ctx *middleware.Context) {
} }
func NewReleasePost(ctx *middleware.Context, form auth.NewReleaseForm) { func NewReleasePost(ctx *middleware.Context, form auth.NewReleaseForm) {
if !ctx.Repo.IsOwner { if !ctx.Repo.IsOwner() {
ctx.Handle(403, "release.ReleasesNew", nil) ctx.Handle(403, "release.ReleasesNew", nil)
return return
} }
@ -211,7 +211,7 @@ func NewReleasePost(ctx *middleware.Context, form auth.NewReleaseForm) {
} }
func EditRelease(ctx *middleware.Context) { func EditRelease(ctx *middleware.Context) {
if !ctx.Repo.IsOwner { if !ctx.Repo.IsOwner() {
ctx.Handle(403, "release.ReleasesEdit", nil) ctx.Handle(403, "release.ReleasesEdit", nil)
return return
} }
@ -234,7 +234,7 @@ func EditRelease(ctx *middleware.Context) {
} }
func EditReleasePost(ctx *middleware.Context, form auth.EditReleaseForm) { func EditReleasePost(ctx *middleware.Context, form auth.EditReleaseForm) {
if !ctx.Repo.IsOwner { if !ctx.Repo.IsOwner() {
ctx.Handle(403, "release.EditReleasePost", nil) ctx.Handle(403, "release.EditReleasePost", nil)
return return
} }

2
routers/repo/repo.go

@ -343,7 +343,7 @@ func Action(ctx *middleware.Context) {
case "unstar": case "unstar":
err = models.StarRepo(ctx.User.Id, ctx.Repo.Repository.Id, false) err = models.StarRepo(ctx.User.Id, ctx.Repo.Repository.Id, false)
case "desc": case "desc":
if !ctx.Repo.IsOwner { if !ctx.Repo.IsOwner() {
ctx.Error(404) ctx.Error(404)
return return
} }

2
templates/repo/header.tmpl

@ -49,7 +49,7 @@
</a> </a>
</li> </li>
<li id="repo-header-fork"> <li id="repo-header-fork">
<a id="repo-header-fork-btn" {{if or (not $.IsRepositoryTrueOwner) $.Owner.IsOrganization}}href="{{AppSubUrl}}/repo/fork?fork_id={{.Id}}"{{end}}> <a id="repo-header-fork-btn" {{if or (not $.IsRepositoryAdmin) $.Owner.IsOrganization}}href="{{AppSubUrl}}/repo/fork?fork_id={{.Id}}"{{end}}>
<button class="btn btn-gray text-bold btn-radius"> <button class="btn btn-gray text-bold btn-radius">
<i class="octicon octicon-repo-forked"></i>{{$.i18n.Tr "repo.fork"}} <i class="octicon octicon-repo-forked"></i>{{$.i18n.Tr "repo.fork"}}
<span class="num">{{.NumForks}}</span> <span class="num">{{.NumForks}}</span>

2
templates/repo/sidebar.tmpl

@ -20,7 +20,7 @@
<!-- <li> <!-- <li>
<a class="radius" href="#"><i class="octicon octicon-organization"></i>contributors <span class="num right label label-gray label-radius">43</span></a> <a class="radius" href="#"><i class="octicon octicon-organization"></i>contributors <span class="num right label label-gray label-radius">43</span></a>
</li> --> </li> -->
{{if .IsRepositoryTrueOwner}} {{if .IsRepositoryAdmin}}
<li class="border-bottom"></li> <li class="border-bottom"></li>
<li> <li>
<a class="radius" href="{{.RepoLink}}/settings"><i class="octicon octicon-tools"></i>{{.i18n.Tr "repo.settings"}}</a> <a class="radius" href="{{.RepoLink}}/settings"><i class="octicon octicon-tools"></i>{{.i18n.Tr "repo.settings"}}</a>

2
templates/repo/toolbar.tmpl

@ -35,7 +35,7 @@
<li><a href="#">Pulse</a></li> <li><a href="#">Pulse</a></li>
<li><a href="#">Network</a></li> <li><a href="#">Network</a></li>
</ul> </ul>
</li> -->{{end}}{{if .IsRepositoryTrueOwner}} </li> -->{{end}}{{if .IsRepositoryAdmin}}
<li class="{{if .IsRepoToolbarSetting}}active{{end}}"><a href="{{.RepoLink}}/settings">Settings</a> <li class="{{if .IsRepoToolbarSetting}}active{{end}}"><a href="{{.RepoLink}}/settings">Settings</a>
</li>{{end}} </li>{{end}}
</ul> </ul>

Loading…
Cancel
Save