aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author65432020-01-02 08:38:42 +0100
committertechknowlogick2020-01-02 02:38:42 -0500
commit17c691f8aaba856bf4e273720d89e53c67b28d75 (patch)
treea6b449964ac2371d17540275c4bf0fda7e9987e4
parentcb3fe4cbf18caa93b2006b801210c02ab4eaf007 (diff)
[Backport] [API] Allow only specific Colums to be updated on Issue (#9539) (#9580)
* Fix #9189 - API Allow only specific Colums to be updated on Issue (#9539) * dont insert "-1" in any case to issue.poster_id * Make sure API cant override importand fields * code format * add Test for IssueEdit * load milestone and return it on IssueEdit via API * extend Test for TestAPIEditIssue * fix TEST * make sure Poster is loaded * keep code format on backport as it is
-rw-r--r--integrations/api_issue_test.go59
-rw-r--r--models/fixtures/issue.yml15
-rw-r--r--models/fixtures/milestone.yml8
-rw-r--r--models/fixtures/repository.yml3
-rw-r--r--models/issue.go40
-rw-r--r--routers/api/v1/repo/issue.go10
-rw-r--r--routers/api/v1/repo/pull.go4
7 files changed, 116 insertions, 23 deletions
diff --git a/integrations/api_issue_test.go b/integrations/api_issue_test.go
index 24535057e..15510fcfc 100644
--- a/integrations/api_issue_test.go
+++ b/integrations/api_issue_test.go
@@ -8,6 +8,7 @@ import (
"fmt"
"net/http"
"testing"
+ "time"
"code.gitea.io/gitea/models"
api "code.gitea.io/gitea/modules/structs"
@@ -62,3 +63,61 @@ func TestAPICreateIssue(t *testing.T) {
Title: title,
})
}
+
+func TestAPIEditIssue(t *testing.T) {
+ prepareTestEnv(t)
+
+ issueBefore := models.AssertExistsAndLoadBean(t, &models.Issue{ID: 9}).(*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 := time.Unix(0, 0)
+ 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,
+ Deadline: &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: 9}).(*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)
+}
diff --git a/models/fixtures/issue.yml b/models/fixtures/issue.yml
index 585242a14..e196cdd57 100644
--- a/models/fixtures/issue.yml
+++ b/models/fixtures/issue.yml
@@ -96,4 +96,17 @@
is_closed: false
is_pull: true
created_unix: 946684820
- updated_unix: 978307180 \ No newline at end of file
+ updated_unix: 978307180
+
+-
+ id: 9
+ 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
diff --git a/models/fixtures/milestone.yml b/models/fixtures/milestone.yml
index 15f422fc3..a9ecb4ee6 100644
--- a/models/fixtures/milestone.yml
+++ b/models/fixtures/milestone.yml
@@ -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
diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml
index cf7d24c6c..a084339cc 100644
--- a/models/fixtures/repository.yml
+++ b/models/fixtures/repository.yml
@@ -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
-
diff --git a/models/issue.go b/models/issue.go
index a129bef7d..7c2eecadb 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -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.
@@ -238,6 +239,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
@@ -251,11 +262,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 {
@@ -295,6 +303,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}
@@ -1730,22 +1743,17 @@ func SearchIssueIDsByKeyword(kw string, repoID int64, limit, start int) (int64,
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 {
+ 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.neuterCrossReferences(sess); err != nil {
diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go
index 6fec1c66b..756b2c35f 100644
--- a/routers/api/v1/repo/issue.go
+++ b/routers/api/v1/repo/issue.go
@@ -352,8 +352,8 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
}
}
- if err = models.UpdateIssue(issue); err != nil {
- ctx.Error(500, "UpdateIssue", err)
+ if err = models.UpdateIssueByAPI(issue); err != nil {
+ ctx.InternalServerError(err)
return
}
if form.State != nil {
@@ -372,7 +372,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(500, "GetIssueByID", err)
+ ctx.InternalServerError(err)
+ return
+ }
+ if err = issue.LoadMilestone(); err != nil {
+ ctx.InternalServerError(err)
return
}
ctx.JSON(201, issue.APIFormat())
diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go
index 2601ab833..0f1be9a6f 100644
--- a/routers/api/v1/repo/pull.go
+++ b/routers/api/v1/repo/pull.go
@@ -420,8 +420,8 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
}
}
- if err = models.UpdateIssue(issue); err != nil {
- ctx.Error(500, "UpdateIssue", err)
+ if err = models.UpdateIssueByAPI(issue); err != nil {
+ ctx.InternalServerError(err)
return
}
if form.State != nil {