Skip to content

Commit

Permalink
Fix #9189 - API Allow only specific Colums to be updated on Issue (#9539
Browse files Browse the repository at this point in the history
)

* dont insert "-1" in any case to issue.poster_id

* Make sure API cant override importand fields

* code format

* fix lint

* WIP test

* add missing poster_id

* fix test

* user.IsGhost handle nil

* CI.restart()

* make sure no -1 is realy added

* CI.restart()

* @lunny suggestion remove some not allowed fields

* seperate issue.LoadMilestone

* load milestone and return it on IssueEdit via API

* extend Test for TestAPIEditIssue

* fix fixtures

* declare allowedColumnsUpdateIssueByAPI only once

* Update Year

* no var just write id drecty into func cal

Co-authored-by: Lauris BH <lauris@nix.lv>
  • Loading branch information
2 people authored and techknowlogick committed Jan 1, 2020
1 parent d1798f7 commit c620eb5
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 29 deletions.
58 changes: 58 additions & 0 deletions integrations/api_issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,61 @@ func TestAPICreateIssue(t *testing.T) {
Title: title,
})
}

func TestAPIEditIssue(t *testing.T) {
defer prepareTestEnv(t)()

issueBefore := models.AssertExistsAndLoadBean(t, &models.Issue{ID: 10}).(*models.Issue)
repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: issueBefore.RepoID}).(*models.Repository)
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
assert.NoError(t, issueBefore.LoadAttributes())
assert.Equal(t, int64(1019307200), int64(issueBefore.DeadlineUnix))
assert.Equal(t, api.StateOpen, issueBefore.State())

session := loginUser(t, owner.Name)
token := getTokenForLoggedInUser(t, session)

// update values of issue
issueState := "closed"
removeDeadline := true
milestone := int64(4)
body := "new content!"
title := "new title from api set"

urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d?token=%s", owner.Name, repo.Name, issueBefore.Index, token)
req := NewRequestWithJSON(t, "PATCH", urlStr, api.EditIssueOption{
State: &issueState,
RemoveDeadline: &removeDeadline,
Milestone: &milestone,
Body: &body,
Title: title,

// ToDo change more
})
resp := session.MakeRequest(t, req, http.StatusCreated)
var apiIssue api.Issue
DecodeJSON(t, resp, &apiIssue)

issueAfter := models.AssertExistsAndLoadBean(t, &models.Issue{ID: 10}).(*models.Issue)

// check deleted user
assert.Equal(t, int64(500), issueAfter.PosterID)
assert.NoError(t, issueAfter.LoadAttributes())
assert.Equal(t, int64(-1), issueAfter.PosterID)
assert.Equal(t, int64(-1), issueBefore.PosterID)
assert.Equal(t, int64(-1), apiIssue.Poster.ID)

// API response
assert.Equal(t, api.StateClosed, apiIssue.State)
assert.Equal(t, milestone, apiIssue.Milestone.ID)
assert.Equal(t, body, apiIssue.Body)
assert.True(t, apiIssue.Deadline == nil)
assert.Equal(t, title, apiIssue.Title)

// in database
assert.Equal(t, api.StateClosed, issueAfter.State())
assert.Equal(t, milestone, issueAfter.MilestoneID)
assert.Equal(t, int64(0), int64(issueAfter.DeadlineUnix))
assert.Equal(t, body, issueAfter.Content)
assert.Equal(t, title, issueAfter.Title)
}
15 changes: 14 additions & 1 deletion models/fixtures/issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,17 @@
is_closed: false
is_pull: true
created_unix: 946684820
updated_unix: 978307180
updated_unix: 978307180

-
id: 10
repo_id: 42
index: 1
poster_id: 500
name: issue from deleted account
content: content from deleted account
is_closed: false
is_pull: false
created_unix: 946684830
updated_unix: 999307200
deadline_unix: 1019307200
8 changes: 8 additions & 0 deletions models/fixtures/milestone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,11 @@
content: content3
is_closed: true
num_issues: 0

-
id: 4
repo_id: 42
name: milestone of repo42
content: content random
is_closed: false
num_issues: 0
9 changes: 5 additions & 4 deletions models/fixtures/repository.yml
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,8 @@
is_private: false
num_stars: 0
num_forks: 0
num_issues: 0
num_issues: 1
num_milestones: 1
is_mirror: false

-
Expand Down Expand Up @@ -588,7 +589,7 @@
is_mirror: false
status: 0

-
-
id: 46
owner_id: 26
lower_name: repo_external_tracker
Expand All @@ -600,7 +601,7 @@
is_mirror: false
status: 0

-
-
id: 47
owner_id: 26
lower_name: repo_external_tracker_numeric
Expand All @@ -612,7 +613,7 @@
is_mirror: false
status: 0

-
-
id: 48
owner_id: 26
lower_name: repo_external_tracker_alpha
Expand Down
44 changes: 25 additions & 19 deletions models/issue.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2020 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.

Expand Down Expand Up @@ -239,6 +240,16 @@ func (issue *Issue) loadReactions(e Engine) (err error) {
return nil
}

func (issue *Issue) loadMilestone(e Engine) (err error) {
if issue.Milestone == nil && issue.MilestoneID > 0 {
issue.Milestone, err = getMilestoneByRepoID(e, issue.RepoID, issue.MilestoneID)
if err != nil && !IsErrMilestoneNotExist(err) {
return fmt.Errorf("getMilestoneByRepoID [repo_id: %d, milestone_id: %d]: %v", issue.RepoID, issue.MilestoneID, err)
}
}
return nil
}

func (issue *Issue) loadAttributes(e Engine) (err error) {
if err = issue.loadRepo(e); err != nil {
return
Expand All @@ -252,11 +263,8 @@ func (issue *Issue) loadAttributes(e Engine) (err error) {
return
}

if issue.Milestone == nil && issue.MilestoneID > 0 {
issue.Milestone, err = getMilestoneByRepoID(e, issue.RepoID, issue.MilestoneID)
if err != nil && !IsErrMilestoneNotExist(err) {
return fmt.Errorf("getMilestoneByRepoID [repo_id: %d, milestone_id: %d]: %v", issue.RepoID, issue.MilestoneID, err)
}
if err = issue.loadMilestone(e); err != nil {
return
}

if err = issue.loadAssignees(e); err != nil {
Expand Down Expand Up @@ -296,6 +304,11 @@ func (issue *Issue) LoadAttributes() error {
return issue.loadAttributes(x)
}

// LoadMilestone load milestone of this issue.
func (issue *Issue) LoadMilestone() error {
return issue.loadMilestone(x)
}

// GetIsRead load the `IsRead` field of the issue
func (issue *Issue) GetIsRead(userID int64) error {
issueUser := &IssueUser{IssueID: issue.ID, UID: userID}
Expand Down Expand Up @@ -1568,25 +1581,18 @@ func SearchIssueIDsByKeyword(kw string, repoIDs []int64, limit, start int) (int6
return total, ids, nil
}

func updateIssue(e Engine, issue *Issue) error {
_, err := e.ID(issue.ID).AllCols().Update(issue)
if err != nil {
return err
}
return nil
}

// UpdateIssue updates all fields of given issue.
func UpdateIssue(issue *Issue) error {
// UpdateIssueByAPI updates all allowed fields of given issue.
func UpdateIssueByAPI(issue *Issue) error {
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}
if err := updateIssue(sess, issue); err != nil {
return err
}
if err := issue.loadPoster(sess); err != nil {

if _, err := sess.ID(issue.ID).Cols(
"name", "is_closed", "content", "milestone_id", "priority",
"deadline_unix", "updated_unix", "closed_unix", "is_locked").
Update(issue); err != nil {
return err
}
if err := issue.addCrossReferences(sess, issue.Poster, true); err != nil {
Expand Down
8 changes: 8 additions & 0 deletions models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,14 @@ func NewGhostUser() *User {
}
}

// IsGhost check if user is fake user for a deleted account
func (u *User) IsGhost() bool {
if u == nil {
return false
}
return u.ID == -1 && u.Name == "Ghost"
}

var (
reservedUsernames = []string{
"attachments",
Expand Down
10 changes: 7 additions & 3 deletions routers/api/v1/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -524,8 +524,8 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
}
}

if err = models.UpdateIssue(issue); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateIssue", err)
if err = models.UpdateIssueByAPI(issue); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateIssueByAPI", err)
return
}
if form.State != nil {
Expand All @@ -542,7 +542,11 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
// Refetch from database to assign some automatic values
issue, err = models.GetIssueByID(issue.ID)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetIssueByID", err)
ctx.InternalServerError(err)
return
}
if err = issue.LoadMilestone(); err != nil {
ctx.InternalServerError(err)
return
}
ctx.JSON(http.StatusCreated, issue.APIFormat())
Expand Down
4 changes: 2 additions & 2 deletions routers/api/v1/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,8 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
}
}

if err = models.UpdateIssue(issue); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateIssue", err)
if err = models.UpdateIssueByAPI(issue); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateIssueByAPI", err)
return
}
if form.State != nil {
Expand Down

0 comments on commit c620eb5

Please sign in to comment.