diff --git a/release-notes/8.0.0/fix/3562.md b/release-notes/8.0.0/fix/3562.md new file mode 100644 index 000000000..809905620 --- /dev/null +++ b/release-notes/8.0.0/fix/3562.md @@ -0,0 +1 @@ +Fixed a bug where subscribing to or unsubscribing from an issue in a repository with no code produced an internal server error. diff --git a/routers/web/repo/issue_watch.go b/routers/web/repo/issue_watch.go index c8d7187b8..5cff9f4dd 100644 --- a/routers/web/repo/issue_watch.go +++ b/routers/web/repo/issue_watch.go @@ -46,7 +46,7 @@ func IssueWatch(ctx *context.Context) { return } - watch, err := strconv.ParseBool(ctx.Req.PostForm.Get("watch")) + watch, err := strconv.ParseBool(ctx.Req.PostFormValue("watch")) if err != nil { ctx.ServerError("watch is not bool", err) return diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index f5b87231f..f6daf0d14 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -692,6 +692,7 @@ type DeclarativeRepoOptions struct { DisabledUnits optional.Option[[]unit_model.Type] Files optional.Option[[]*files_service.ChangeRepoFile] WikiBranch optional.Option[string] + AutoInit optional.Option[bool] } func CreateDeclarativeRepoWithOptions(t *testing.T, owner *user_model.User, opts DeclarativeRepoOptions) (*repo_model.Repository, string, func()) { @@ -706,11 +707,18 @@ func CreateDeclarativeRepoWithOptions(t *testing.T, owner *user_model.User, opts repoName = gouuid.NewString() } + var autoInit bool + if opts.AutoInit.Has() { + autoInit = opts.AutoInit.Value() + } else { + autoInit = true + } + // Create the repository repo, err := repo_service.CreateRepository(db.DefaultContext, owner, owner, repo_service.CreateRepoOptions{ Name: repoName, Description: "Temporary Repo", - AutoInit: true, + AutoInit: autoInit, Gitignores: "", License: "WTFPL", Readme: "Default", @@ -742,6 +750,7 @@ func CreateDeclarativeRepoWithOptions(t *testing.T, owner *user_model.User, opts // Add files, if any. var sha string if opts.Files.Has() { + assert.True(t, autoInit, "Files cannot be specified if AutoInit is disabled") files := opts.Files.Value() resp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, owner, &files_service.ChangeRepoFilesOptions{ diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go index 49d1cbb01..e09656c4e 100644 --- a/tests/integration/issue_test.go +++ b/tests/integration/issue_test.go @@ -22,6 +22,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/indexer/issues" + "code.gitea.io/gitea/modules/optional" "code.gitea.io/gitea/modules/references" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -876,3 +877,23 @@ body: }) }) } + +func TestIssueUnsubscription(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + defer tests.PrepareTestEnv(t)() + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + repo, _, f := CreateDeclarativeRepoWithOptions(t, user, DeclarativeRepoOptions{ + AutoInit: optional.Some(false), + }) + defer f() + session := loginUser(t, user.Name) + + issueURL := testNewIssue(t, session, user.Name, repo.Name, "Issue title", "Description") + req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/watch", issueURL), map[string]string{ + "_csrf": GetCSRF(t, session, issueURL), + "watch": "0", + }) + session.MakeRequest(t, req, http.StatusOK) + }) +}