Skip to content

Check for permission when fetching user controlled issues (#20133) #20196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions models/issue_milestone.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ func getMilestoneByRepoID(e db.Engine, repoID, id int64) (*Milestone, error) {
return m, nil
}

// HasMilestoneByRepoID returns if the milestone exists in the repository.
func HasMilestoneByRepoID(repoID, id int64) (bool, error) {
return db.GetEngine(db.DefaultContext).ID(id).Where("repo_id=?", repoID).Exist(new(Milestone))
}

// GetMilestoneByRepoID returns the milestone in a repository.
func GetMilestoneByRepoID(repoID, id int64) (*Milestone, error) {
return getMilestoneByRepoID(db.GetEngine(db.DefaultContext), repoID, id)
Expand Down Expand Up @@ -251,6 +256,17 @@ func changeMilestoneStatus(ctx context.Context, m *Milestone, isClosed bool) err
}

func changeMilestoneAssign(ctx context.Context, doer *user_model.User, issue *Issue, oldMilestoneID int64) error {
// Only check if milestone exists if we don't remove it.
if issue.MilestoneID > 0 {
has, err := HasMilestoneByRepoID(issue.RepoID, issue.MilestoneID)
if err != nil {
return fmt.Errorf("HasMilestoneByRepoID: %v", err)
}
if !has {
return fmt.Errorf("HasMilestoneByRepoID: issue doesn't exist")
}
}

if err := updateIssueCols(ctx, issue, "milestone_id"); err != nil {
return err
}
Expand Down
11 changes: 11 additions & 0 deletions models/project_issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,17 @@ func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.U
e := db.GetEngine(ctx)
oldProjectID := issue.projectID(e)

// Only check if we add a new project and not remove it.
if newProjectID > 0 {
newProject, err := GetProjectByID(newProjectID)
if err != nil {
return err
}
if newProject.RepoID != issue.RepoID {
return fmt.Errorf("issue's repository is not the same as project's repository")
}
}

if _, err := e.Where("project_issue.issue_id=?", issue.ID).Delete(&ProjectIssue{}); err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion routers/api/v1/repo/pull_review.go
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@ func dismissReview(ctx *context.APIContext, msg string, isDismiss bool) {
return
}

_, err := pull_service.DismissReview(review.ID, msg, ctx.User, isDismiss)
_, err := pull_service.DismissReview(review.ID, ctx.Repo.Repository.ID, msg, ctx.User, isDismiss)
if err != nil {
ctx.Error(http.StatusInternalServerError, "pull_service.DismissReview", err)
return
Expand Down
48 changes: 28 additions & 20 deletions routers/web/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,15 @@ const (
issueTemplateTitleKey = "IssueTemplateTitle"
)

var (
// IssueTemplateCandidates issue templates
IssueTemplateCandidates = []string{
"ISSUE_TEMPLATE.md",
"issue_template.md",
".gitea/ISSUE_TEMPLATE.md",
".gitea/issue_template.md",
".github/ISSUE_TEMPLATE.md",
".github/issue_template.md",
}
)
// IssueTemplateCandidates issue templates
var IssueTemplateCandidates = []string{
"ISSUE_TEMPLATE.md",
"issue_template.md",
".gitea/ISSUE_TEMPLATE.md",
".gitea/issue_template.md",
".github/ISSUE_TEMPLATE.md",
".github/issue_template.md",
}

// MustAllowUserComment checks to make sure if an issue is locked.
// If locked and user has permissions to write to the repository,
Expand Down Expand Up @@ -245,7 +243,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
}
}

var issueList = models.IssueList(issues)
issueList := models.IssueList(issues)
approvalCounts, err := issueList.GetApprovalCounts()
if err != nil {
ctx.ServerError("ApprovalCounts", err)
Expand Down Expand Up @@ -311,8 +309,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
assigneeID = 0 // Reset ID to prevent unexpected selection of assignee.
}

ctx.Data["IssueRefEndNames"], ctx.Data["IssueRefURLs"] =
issue_service.GetRefEndNamesAndURLs(issues, ctx.Repo.RepoLink)
ctx.Data["IssueRefEndNames"], ctx.Data["IssueRefURLs"] = issue_service.GetRefEndNamesAndURLs(issues, ctx.Repo.RepoLink)

ctx.Data["ApprovalCounts"] = func(issueID int64, typ string) int64 {
counts, ok := approvalCounts[issueID]
Expand Down Expand Up @@ -442,7 +439,6 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.R
}

func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {

var err error

ctx.Data["OpenProjects"], _, err = models.GetProjects(models.ProjectSearchOptions{
Expand Down Expand Up @@ -796,7 +792,8 @@ func NewIssue(ctx *context.Context) {
body := ctx.FormString("body")
ctx.Data["BodyQuery"] = body

ctx.Data["IsProjectsEnabled"] = ctx.Repo.CanRead(unit.TypeProjects)
isProjectsEnabled := ctx.Repo.CanRead(unit.TypeProjects)
ctx.Data["IsProjectsEnabled"] = isProjectsEnabled
ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled
upload.AddUploadContext(ctx, "comment")

Expand All @@ -812,7 +809,7 @@ func NewIssue(ctx *context.Context) {
}

projectID := ctx.FormInt64("project")
if projectID > 0 {
if projectID > 0 && isProjectsEnabled {
project, err := models.GetProjectByID(projectID)
if err != nil {
log.Error("GetProjectByID: %d: %v", projectID, err)
Expand Down Expand Up @@ -1017,6 +1014,12 @@ func NewIssuePost(ctx *context.Context) {
}

if projectID > 0 {
if !ctx.Repo.CanRead(unit.TypeProjects) {
// User must also be able to see the project.
ctx.Error(http.StatusBadRequest, "user hasn't permissions to read projects")
return
}

if err := models.ChangeProjectAssign(issue, ctx.User, projectID); err != nil {
ctx.ServerError("ChangeProjectAssign", err)
return
Expand Down Expand Up @@ -1713,6 +1716,11 @@ func getActionIssues(ctx *context.Context) []*models.Issue {
issueUnitEnabled := ctx.Repo.CanRead(unit.TypeIssues)
prUnitEnabled := ctx.Repo.CanRead(unit.TypePullRequests)
for _, issue := range issues {
if issue.RepoID != ctx.Repo.Repository.ID {
ctx.NotFound("some issue's RepoID is incorrect", errors.New("some issue's RepoID is incorrect"))
return nil
}

if issue.IsPull && !prUnitEnabled || !issue.IsPull && !issueUnitEnabled {
ctx.NotFound("IssueOrPullRequestUnitNotAllowed", nil)
return nil
Expand Down Expand Up @@ -2515,7 +2523,7 @@ func filterXRefComments(ctx *context.Context, issue *models.Issue) error {
// GetIssueAttachments returns attachments for the issue
func GetIssueAttachments(ctx *context.Context) {
issue := GetActionIssue(ctx)
var attachments = make([]*api.Attachment, len(issue.Attachments))
attachments := make([]*api.Attachment, len(issue.Attachments))
for i := 0; i < len(issue.Attachments); i++ {
attachments[i] = convert.ToReleaseAttachment(issue.Attachments[i])
}
Expand All @@ -2529,7 +2537,7 @@ func GetCommentAttachments(ctx *context.Context) {
ctx.NotFoundOrServerError("GetCommentByID", models.IsErrCommentNotExist, err)
return
}
var attachments = make([]*api.Attachment, 0)
attachments := make([]*api.Attachment, 0)
if comment.Type == models.CommentTypeComment {
if err := comment.LoadAttachments(); err != nil {
ctx.ServerError("LoadAttachments", err)
Expand Down Expand Up @@ -2674,7 +2682,7 @@ func handleTeamMentions(ctx *context.Context) {
var isAdmin bool
var err error
var teams []*models.Team
var org = models.OrgFromUser(ctx.Repo.Owner)
org := models.OrgFromUser(ctx.Repo.Owner)
// Admin has super access.
if ctx.User.IsAdmin {
isAdmin = true
Expand Down
11 changes: 9 additions & 2 deletions routers/web/repo/projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package repo

import (
"errors"
"fmt"
"net/http"
"net/url"
Expand Down Expand Up @@ -531,7 +532,6 @@ func EditProjectBoard(ctx *context.Context) {

// SetDefaultProjectBoard set default board for uncategorized issues/pulls
func SetDefaultProjectBoard(ctx *context.Context) {

project, board := checkProjectBoardChangePermissions(ctx)
if ctx.Written() {
return
Expand Down Expand Up @@ -631,10 +631,17 @@ func MoveIssues(ctx *context.Context) {
}

if len(movedIssues) != len(form.Issues) {
ctx.ServerError("IssuesNotFound", err)
ctx.ServerError("some issues do not exist", errors.New("some issues do not exist"))
return
}

for _, issue := range movedIssues {
if issue.RepoID != project.RepoID {
ctx.ServerError("Some issue's repoID is not equal to project's repoID", errors.New("Some issue's repoID is not equal to project's repoID"))
return
}
}

if err = models.MoveIssuesOnProjectBoard(board, sortedIssueIDs); err != nil {
ctx.ServerError("MoveIssuesOnProjectBoard", err)
return
Expand Down
8 changes: 7 additions & 1 deletion routers/web/repo/pull_review.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package repo

import (
"errors"
"fmt"
"net/http"

Expand Down Expand Up @@ -116,6 +117,11 @@ func UpdateResolveConversation(ctx *context.Context) {
return
}

if comment.Issue.RepoID != ctx.Repo.Repository.ID {
ctx.NotFound("comment's repoID is incorrect", errors.New("comment's repoID is incorrect"))
return
}

var permResult bool
if permResult, err = models.CanMarkConversation(comment.Issue, ctx.User); err != nil {
ctx.ServerError("CanMarkConversation", err)
Expand Down Expand Up @@ -234,7 +240,7 @@ func SubmitReview(ctx *context.Context) {
// DismissReview dismissing stale review by repo admin
func DismissReview(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.DismissReviewForm)
comm, err := pull_service.DismissReview(form.ReviewID, form.Message, ctx.User, true)
comm, err := pull_service.DismissReview(form.ReviewID, ctx.Repo.Repository.ID, form.Message, ctx.User, true)
if err != nil {
ctx.ServerError("pull_service.DismissReview", err)
return
Expand Down
16 changes: 11 additions & 5 deletions services/pull/review.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func SubmitReview(doer *user_model.User, gitRepo *git.Repository, issue *models.
}

// DismissReview dismissing stale review by repo admin
func DismissReview(reviewID int64, message string, doer *user_model.User, isDismiss bool) (comment *models.Comment, err error) {
func DismissReview(reviewID, repoID int64, message string, doer *user_model.User, isDismiss bool) (comment *models.Comment, err error) {
review, err := models.GetReviewByID(reviewID)
if err != nil {
return
Expand All @@ -281,6 +281,16 @@ func DismissReview(reviewID int64, message string, doer *user_model.User, isDism
return nil, fmt.Errorf("not need to dismiss this review because it's type is not Approve or change request")
}

// load data for notify
if err = review.LoadAttributes(); err != nil {
return nil, err
}

// Check if the review's repoID is the one we're currently expecting.
if review.Issue.RepoID != repoID {
return nil, fmt.Errorf("reviews's repository is not the same as the one we expect")
}

if err = models.DismissReview(review, isDismiss); err != nil {
return
}
Expand All @@ -289,10 +299,6 @@ func DismissReview(reviewID int64, message string, doer *user_model.User, isDism
return nil, nil
}

// load data for notify
if err = review.LoadAttributes(); err != nil {
return
}
if err = review.Issue.LoadPullRequest(); err != nil {
return
}
Expand Down