Merge pull request 'fix: validate title length when updating an issue' (#4809) from thilinajayanath/forgejo:validate-issue-title-update into forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/4809
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Reviewed-by: Otto <otto@codeberg.org>
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
This commit is contained in:
Otto 2024-08-21 12:55:26 +00:00
commit c20c534b90
2 changed files with 75 additions and 3 deletions

View file

@ -57,6 +57,8 @@ import (
issue_service "code.gitea.io/gitea/services/issue" issue_service "code.gitea.io/gitea/services/issue"
pull_service "code.gitea.io/gitea/services/pull" pull_service "code.gitea.io/gitea/services/pull"
repo_service "code.gitea.io/gitea/services/repository" repo_service "code.gitea.io/gitea/services/repository"
"gitea.com/go-chi/binding"
) )
const ( const (
@ -2218,10 +2220,20 @@ func UpdateIssueTitle(ctx *context.Context) {
ctx.Error(http.StatusForbidden) ctx.Error(http.StatusForbidden)
return return
} }
title := ctx.FormTrim("title") title := ctx.FormTrim("title")
if len(title) == 0 { if util.IsEmptyString(title) {
ctx.Error(http.StatusNoContent) 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 return
} }

View file

@ -1005,6 +1005,66 @@ func TestUpdateIssueDeadline(t *testing.T) {
assert.EqualValues(t, "2022-04-06", apiIssue.Deadline.Format("2006-01-02")) 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) { func TestIssueReferenceURL(t *testing.T) {
defer tests.PrepareTestEnv(t)() defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user2") session := loginUser(t, "user2")