From 1e922d906f60cb262abee1eb23dad906c8521abe Mon Sep 17 00:00:00 2001 From: thilinajayanath Date: Sun, 4 Aug 2024 17:30:06 +0200 Subject: [PATCH] validate the title length when updating an issue and add integration test for issue title update using middleware validator to validate title length on update use error name from binding package add integration test for title update rebase upstream and update test var name fix test slice formatting just a try (#1) Reviewed-on: https://codeberg.org/thilinajayanath/forgejo/pulls/1 Co-authored-by: Otto Richter Co-committed-by: Otto Richter fix errors + add test for 255 char title fix test domain fix CSRF token error on test updaate result struct that's used to decode the json response add json tags for struct and check changed title when http 200 is received try to decode the title if the request succeeded add comment in integration test --- routers/web/repo/issue.go | 18 ++++++++-- tests/integration/issue_test.go | 60 +++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 055fcdc231..f8c50af53c 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -57,6 +57,8 @@ import ( issue_service "code.gitea.io/gitea/services/issue" pull_service "code.gitea.io/gitea/services/pull" repo_service "code.gitea.io/gitea/services/repository" + + "gitea.com/go-chi/binding" ) const ( @@ -2218,10 +2220,20 @@ func UpdateIssueTitle(ctx *context.Context) { ctx.Error(http.StatusForbidden) return } - title := ctx.FormTrim("title") - if len(title) == 0 { - ctx.Error(http.StatusNoContent) + if util.IsEmptyString(title) { + ctx.Error(http.StatusBadRequest, "Title cannot be empty or spaces") + return + } + + // Creating a CreateIssueForm with the title so that we can validate the max title length + i := forms.CreateIssueForm{ + Title: title, + } + + bindingErr := binding.RawValidate(i) + if bindingErr.Has(binding.ERR_MAX_SIZE) { + ctx.Error(http.StatusBadRequest, "Title cannot be longer than 255 characters") return } diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go index 846de8f42c..ecdda68196 100644 --- a/tests/integration/issue_test.go +++ b/tests/integration/issue_test.go @@ -1005,6 +1005,66 @@ func TestUpdateIssueDeadline(t *testing.T) { assert.EqualValues(t, "2022-04-06", apiIssue.Deadline.Format("2006-01-02")) } +func TestUpdateIssueTitle(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + issueBefore := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issueBefore.RepoID}) + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + + require.NoError(t, issueBefore.LoadAttributes(db.DefaultContext)) + assert.Equal(t, "issue1", issueBefore.Title) + + issueTitleUpdateTests := []struct { + title string + expectedHTTPCode int + }{ + { + title: "normal-title", + expectedHTTPCode: http.StatusOK, + }, + { + title: "extra-long-title-with-exactly-255-chars-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + expectedHTTPCode: http.StatusOK, + }, + { + title: "", + expectedHTTPCode: http.StatusBadRequest, + }, + { + title: " ", + expectedHTTPCode: http.StatusBadRequest, + }, + { + title: "extra-long-title-over-255-chars-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + expectedHTTPCode: http.StatusBadRequest, + }, + } + + session := loginUser(t, owner.Name) + issueURL := fmt.Sprintf("%s/%s/issues/%d", owner.Name, repo.Name, issueBefore.Index) + urlStr := issueURL + "/title" + + for _, issueTitleUpdateTest := range issueTitleUpdateTests { + req := NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "title": issueTitleUpdateTest.title, + "_csrf": GetCSRF(t, session, issueURL), + }) + + resp := session.MakeRequest(t, req, issueTitleUpdateTest.expectedHTTPCode) + + // JSON data is received only if the request succeeds + if issueTitleUpdateTest.expectedHTTPCode == http.StatusOK { + issueAfter := struct { + Title string `json:"title"` + }{} + + DecodeJSON(t, resp, &issueAfter) + assert.EqualValues(t, issueTitleUpdateTest.title, issueAfter.Title) + } + } +} + func TestIssueReferenceURL(t *testing.T) { defer tests.PrepareTestEnv(t)() session := loginUser(t, "user2")