diff --git a/routers/web/web.go b/routers/web/web.go index 6b649dc1f5..98cdf8b964 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1225,10 +1225,11 @@ func registerWebRoutes(m *web.Router) { // end "/{username}/{reponame}": view milestone, label, issue, pull, etc m.Group("/{username}/{reponame}/{type:issues}", func() { + // these handlers also check unit permissions internally m.Get("", repo.Issues) - m.Get("/{index}", repo.ViewIssue) - }, optSignIn, context.RepoAssignment, context.RequireUnitReader(unit.TypeIssues, unit.TypeExternalTracker)) - // end "/{username}/{reponame}": issue/pull list, issue/pull view, external tracker + m.Get("/{index}", repo.ViewIssue) // also do pull-request redirection (".../issues/{PR-number}" -> ".../pulls/{PR-number}") + }, optSignIn, context.RepoAssignment, context.RequireUnitReader(unit.TypeIssues, unit.TypePullRequests, unit.TypeExternalTracker)) + // end "/{username}/{reponame}": issue list, issue view (pull-request redirection), external tracker m.Group("/{username}/{reponame}", func() { // edit issues, pulls, labels, milestones, etc m.Group("/issues", func() { diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go index 3b5f1534ef..613353e55c 100644 --- a/tests/integration/issue_test.go +++ b/tests/integration/issue_test.go @@ -14,8 +14,10 @@ import ( "testing" "time" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/indexer/issues" @@ -474,19 +476,38 @@ func TestIssueRedirect(t *testing.T) { session := loginUser(t, "user2") // Test external tracker where style not set (shall default numeric) - req := NewRequest(t, "GET", path.Join("org26", "repo_external_tracker", "issues", "1")) + req := NewRequest(t, "GET", "/org26/repo_external_tracker/issues/1") resp := session.MakeRequest(t, req, http.StatusSeeOther) assert.Equal(t, "https://tracker.com/org26/repo_external_tracker/issues/1", test.RedirectURL(resp)) // Test external tracker with numeric style - req = NewRequest(t, "GET", path.Join("org26", "repo_external_tracker_numeric", "issues", "1")) + req = NewRequest(t, "GET", "/org26/repo_external_tracker_numeric/issues/1") resp = session.MakeRequest(t, req, http.StatusSeeOther) assert.Equal(t, "https://tracker.com/org26/repo_external_tracker_numeric/issues/1", test.RedirectURL(resp)) // Test external tracker with alphanumeric style (for a pull request) - req = NewRequest(t, "GET", path.Join("org26", "repo_external_tracker_alpha", "issues", "1")) + req = NewRequest(t, "GET", "/org26/repo_external_tracker_alpha/issues/1") resp = session.MakeRequest(t, req, http.StatusSeeOther) - assert.Equal(t, "/"+path.Join("org26", "repo_external_tracker_alpha", "pulls", "1"), test.RedirectURL(resp)) + assert.Equal(t, "/org26/repo_external_tracker_alpha/pulls/1", test.RedirectURL(resp)) + + // test to check that the PR redirection works if the issue unit is disabled + // repo1 is a normal repository with issue unit enabled, visit issue 2(which is a pull request) + // will redirect to pulls + req = NewRequest(t, "GET", "/user2/repo1/issues/2") + resp = session.MakeRequest(t, req, http.StatusSeeOther) + assert.Equal(t, "/user2/repo1/pulls/2", test.RedirectURL(resp)) + + repoUnit := unittest.AssertExistsAndLoadBean(t, &repo_model.RepoUnit{RepoID: 1, Type: unit.TypeIssues}) + + // disable issue unit, it will be reset + _, err := db.DeleteByID[repo_model.RepoUnit](t.Context(), repoUnit.ID) + assert.NoError(t, err) + + // even if the issue unit is disabled, visiting an issue which is a pull request + // will still redirect to pull request + req = NewRequest(t, "GET", "/user2/repo1/issues/2") + resp = session.MakeRequest(t, req, http.StatusSeeOther) + assert.Equal(t, "/user2/repo1/pulls/2", test.RedirectURL(resp)) } func TestSearchIssues(t *testing.T) {