Skip to content

Commit

Permalink
Fix wrong permissions check when issues/prs shared operations (go-git…
Browse files Browse the repository at this point in the history
…ea#9885) (go-gitea#9889)

* Fix wrong permissions check when issues/prs shared operations

* move redirect to the last of the function

* fix swagger

Co-authored-by: zeripath <[email protected]>
Co-authored-by: Lauris BH <[email protected]>
  • Loading branch information
3 people committed Jan 20, 2020
1 parent ce756ee commit f96c1a2
Show file tree
Hide file tree
Showing 11 changed files with 43 additions and 28 deletions.
2 changes: 1 addition & 1 deletion modules/context/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ 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.Permission.CanWrite(models.UnitTypeIssues) || issue.IsPoster(user.ID) || isAssigned)
r.Permission.CanWriteIssuesOrPulls(issue.IsPull) || issue.IsPoster(user.ID) || isAssigned)
}

// CanCreateIssueDependencies returns whether or not a user can create dependencies.
Expand Down
4 changes: 2 additions & 2 deletions modules/repofiles/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ func UpdateIssuesCommit(doer *models.User, repo *models.Repository, commits []*m
refMarked[key] = true

// FIXME: this kind of condition is all over the code, it should be consolidated in a single place
canclose := perm.IsAdmin() || perm.IsOwner() || perm.CanWrite(models.UnitTypeIssues) || refIssue.PosterID == doer.ID
cancomment := canclose || perm.CanRead(models.UnitTypeIssues)
canclose := perm.IsAdmin() || perm.IsOwner() || perm.CanWriteIssuesOrPulls(refIssue.IsPull) || refIssue.PosterID == doer.ID
cancomment := canclose || perm.CanReadIssuesOrPulls(refIssue.IsPull)

// Don't proceed if the user can't comment
if !cancomment {
Expand Down
26 changes: 21 additions & 5 deletions routers/api/v1/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ func ListIssues(ctx *context.APIContext) {
// in: query
// description: search string
// type: string
// - name: type
// in: query
// description: filter by type (issues / pulls) if set
// type: string
// responses:
// "200":
// "$ref": "#/responses/IssueList"
Expand Down Expand Up @@ -242,6 +246,16 @@ func ListIssues(ctx *context.APIContext) {
}
}

var isPull util.OptionalBool
switch ctx.Query("type") {
case "pulls":
isPull = util.OptionalBoolTrue
case "issues":
isPull = util.OptionalBoolFalse
default:
isPull = util.OptionalBoolNone
}

// Only fetch the issues if we either don't have a keyword or the search returned issues
// This would otherwise return all issues if no issues were found by the search.
if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
Expand All @@ -252,6 +266,7 @@ func ListIssues(ctx *context.APIContext) {
IsClosed: isClosed,
IssueIDs: issueIDs,
LabelIDs: labelIDs,
IsPull: isPull,
})
}

Expand Down Expand Up @@ -476,14 +491,15 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
return
}
issue.Repo = ctx.Repo.Repository
canWrite := ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)

err = issue.LoadAttributes()
if err != nil {
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
return
}

if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWrite(models.UnitTypeIssues) {
if !issue.IsPoster(ctx.User.ID) && !canWrite {
ctx.Status(http.StatusForbidden)
return
}
Expand All @@ -496,7 +512,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
}

// Update or remove the deadline, only if set and allowed
if (form.Deadline != nil || form.RemoveDeadline != nil) && ctx.Repo.CanWrite(models.UnitTypeIssues) {
if (form.Deadline != nil || form.RemoveDeadline != nil) && canWrite {
var deadlineUnix timeutil.TimeStamp

if (form.RemoveDeadline == nil || !*form.RemoveDeadline) && !form.Deadline.IsZero() {
Expand All @@ -520,7 +536,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
// Pass one or more user logins to replace the set of assignees on this Issue.
// Send an empty array ([]) to clear all assignees from the Issue.

if ctx.Repo.CanWrite(models.UnitTypeIssues) && (form.Assignees != nil || form.Assignee != nil) {
if canWrite && (form.Assignees != nil || form.Assignee != nil) {
oneAssignee := ""
if form.Assignee != nil {
oneAssignee = *form.Assignee
Expand All @@ -533,7 +549,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
}
}

if ctx.Repo.CanWrite(models.UnitTypeIssues) && form.Milestone != nil &&
if canWrite && form.Milestone != nil &&
issue.MilestoneID != *form.Milestone {
oldMilestoneID := issue.MilestoneID
issue.MilestoneID = *form.Milestone
Expand Down Expand Up @@ -619,7 +635,7 @@ func UpdateIssueDeadline(ctx *context.APIContext, form api.EditDeadlineOption) {
return
}

if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
ctx.Error(http.StatusForbidden, "", "Not repo writer")
return
}
Expand Down
2 changes: 1 addition & 1 deletion routers/api/v1/repo/issue_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOpti
return
}

if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin {
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.User.IsAdmin {
ctx.Error(http.StatusForbidden, "CreateIssueComment", errors.New(ctx.Tr("repo.issues.comment_on_locked")))
return
}
Expand Down
4 changes: 2 additions & 2 deletions routers/api/v1/repo/issue_reaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp
ctx.Error(http.StatusInternalServerError, "comment.LoadIssue() failed", err)
}

if comment.Issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) {
if comment.Issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull) {
ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction"))
return
}
Expand Down Expand Up @@ -380,7 +380,7 @@ func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, i
return
}

if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) {
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
ctx.Error(http.StatusForbidden, "ChangeIssueCommentReaction", errors.New("no permission to change reaction"))
return
}
Expand Down
2 changes: 1 addition & 1 deletion routers/api/v1/repo/issue_stopwatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func prepareIssueStopwatch(ctx *context.APIContext, shouldExist bool) (*models.I
return nil, err
}

if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
if !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) {
ctx.Status(http.StatusForbidden)
return nil, err
}
Expand Down
9 changes: 4 additions & 5 deletions routers/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,12 @@ var (
// If locked and user has permissions to write to the repository,
// then the comment is allowed, else it is blocked
func MustAllowUserComment(ctx *context.Context) {

issue := GetActionIssue(ctx)
if ctx.Written() {
return
}

if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin {
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.User.IsAdmin {
ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked"))
ctx.Redirect(issue.HTMLURL())
return
Expand Down Expand Up @@ -349,7 +348,7 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *models.Repos

// RetrieveRepoMetas find all the meta information of a repository
func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository, isPull bool) []*models.Label {
if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
if !ctx.Repo.CanWriteIssuesOrPulls(isPull) {
return nil
}

Expand Down Expand Up @@ -1006,7 +1005,6 @@ func ViewIssue(ctx *context.Context) {
ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.User.ID)
ctx.Data["IsIssueWriter"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
ctx.Data["IsRepoAdmin"] = ctx.IsSigned && (ctx.Repo.IsAdmin() || ctx.User.IsAdmin)
ctx.Data["IsRepoIssuesWriter"] = ctx.IsSigned && (ctx.Repo.CanWrite(models.UnitTypeIssues) || ctx.User.IsAdmin)
ctx.Data["LockReasons"] = setting.Repository.Issue.LockReasons
ctx.HTML(200, tplIssueView)
}
Expand Down Expand Up @@ -1267,9 +1265,10 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
}

ctx.Error(403)
return
}

if issue.IsLocked && !ctx.Repo.CanWrite(models.UnitTypeIssues) && !ctx.User.IsAdmin {
if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.User.IsAdmin {
ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked"))
ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther)
return
Expand Down
6 changes: 3 additions & 3 deletions routers/repo/issue_dependency.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,6 @@ func RemoveDependency(ctx *context.Context) {
return
}

// Redirect
ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther)

// Dependency Type
depTypeStr := ctx.Req.PostForm.Get("dependencyType")

Expand Down Expand Up @@ -126,4 +123,7 @@ func RemoveDependency(ctx *context.Context) {
ctx.ServerError("RemoveIssueDependency", err)
return
}

// Redirect
ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther)
}
8 changes: 1 addition & 7 deletions routers/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -503,19 +503,13 @@ func RegisterRoutes(m *macaron.Macaron) {
reqRepoReleaseWriter := context.RequireRepoWriter(models.UnitTypeReleases)
reqRepoReleaseReader := context.RequireRepoReader(models.UnitTypeReleases)
reqRepoWikiWriter := context.RequireRepoWriter(models.UnitTypeWiki)
reqRepoIssueWriter := context.RequireRepoWriter(models.UnitTypeIssues)
reqRepoIssueReader := context.RequireRepoReader(models.UnitTypeIssues)
reqRepoPullsWriter := context.RequireRepoWriter(models.UnitTypePullRequests)
reqRepoPullsReader := context.RequireRepoReader(models.UnitTypePullRequests)
reqRepoIssuesOrPullsWriter := context.RequireRepoWriterOr(models.UnitTypeIssues, models.UnitTypePullRequests)
reqRepoIssuesOrPullsReader := context.RequireRepoReaderOr(models.UnitTypeIssues, models.UnitTypePullRequests)

reqRepoIssueWriter := func(ctx *context.Context) {
if !ctx.Repo.CanWrite(models.UnitTypeIssues) {
ctx.Error(403)
return
}
}

// ***** START: Organization *****
m.Group("/org", func() {
m.Group("", func() {
Expand Down
2 changes: 1 addition & 1 deletion templates/repo/issue/view_content.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
{{ template "repo/issue/view_content/pull". }}
{{end}}
{{if .IsSigned}}
{{ if and (or .IsRepoAdmin .IsRepoIssuesWriter (or (not .Issue.IsLocked))) (not .Repository.IsArchived) }}
{{ if and (or .IsRepoAdmin .IsIssueWriter (or (not .Issue.IsLocked))) (not .Repository.IsArchived) }}
<div class="comment form">
<a class="avatar" href="{{.SignedUser.HomeLink}}">
<img src="{{.SignedUser.RelAvatarLink}}">
Expand Down
6 changes: 6 additions & 0 deletions templates/swagger/v1_json.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2909,6 +2909,12 @@
"description": "search string",
"name": "q",
"in": "query"
},
{
"type": "string",
"description": "filter by type (issues / pulls) if set",
"name": "type",
"in": "query"
}
],
"responses": {
Expand Down

0 comments on commit f96c1a2

Please sign in to comment.