From 379c2684fac18265f05b3ef3ff0d67ac03829af0 Mon Sep 17 00:00:00 2001 From: oliverpool Date: Thu, 19 Jun 2025 18:35:09 +0200 Subject: [PATCH] fix: collaborator can edit wiki with write access (#8234) fixes: #8119, replaces #8135 Bug likely introduced in 5eeccecafc578e1b1d9ce4e7503bcc0812a04be4 ### Tests - I added test coverage for Go changes in the `tests/integration` directory if it involves interactions with a live Forgejo server. ### Documentation - [x] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [x] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/.md` to be be used for the release notes instead of the title. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8234 Reviewed-by: Earl Warren Co-authored-by: oliverpool Co-committed-by: oliverpool (cherry picked from commit 913eaffb8ac3cb3394f240e40cc7134d0483f970) --- tests/integration/repo_wiki_test.go | 101 ++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/tests/integration/repo_wiki_test.go b/tests/integration/repo_wiki_test.go index d492f2ed90..fd6e045f55 100644 --- a/tests/integration/repo_wiki_test.go +++ b/tests/integration/repo_wiki_test.go @@ -216,3 +216,104 @@ func TestWikiPermissions(t *testing.T) { }) }) } + +func canEditWiki(t *testing.T, username, url string, canEdit bool) { + t.Helper() + // t.Parallel() + + req := NewRequest(t, "GET", url) + + var resp *httptest.ResponseRecorder + if username != "" { + session := loginUser(t, username) + resp = session.MakeRequest(t, req, http.StatusOK) + } else { + resp = MakeRequest(t, req, http.StatusOK) + } + doc := NewHTMLParser(t, resp.Body) + res := doc.Find(`a[href^="` + url + `"]`).Map(func(_ int, el *goquery.Selection) string { + return el.AttrOr("href", "") + }) + found := false + for _, href := range res { + if strings.HasSuffix(href, "?action=_new") { + if !canEdit { + t.Errorf("unexpected edit link: %s", href) + } + found = true + break + } + } + if canEdit { + assert.True(t, found, "could not find ?action=_new link among %v", res) + } +} + +func TestWikiPermissions(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + t.Run("default settings", func(t *testing.T) { + t.Run("anonymous", func(t *testing.T) { + canEditWiki(t, "", "/user5/repo4/wiki", false) + }) + t.Run("owner", func(t *testing.T) { + canEditWiki(t, "user5", "/user5/repo4/wiki", true) + }) + t.Run("collaborator", func(t *testing.T) { + canEditWiki(t, "user4", "/user5/repo4/wiki", true) + canEditWiki(t, "user29", "/user5/repo4/wiki", true) + }) + t.Run("other user", func(t *testing.T) { + canEditWiki(t, "user2", "/user5/repo4/wiki", false) + }) + }) + + t.Run("saved unchanged settings", func(t *testing.T) { + session := loginUser(t, "user5") + csrf := GetCSRF(t, session, "/user5/repo4/settings/units") + req := NewRequestWithValues(t, "POST", "/user5/repo4/settings/units", map[string]string{ + "_csrf": csrf, + "enable_wiki": "on", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + t.Run("anonymous", func(t *testing.T) { + canEditWiki(t, "", "/user5/repo4/wiki", false) + }) + t.Run("owner", func(t *testing.T) { + canEditWiki(t, "user5", "/user5/repo4/wiki", true) + }) + t.Run("collaborator", func(t *testing.T) { + canEditWiki(t, "user4", "/user5/repo4/wiki", true) + canEditWiki(t, "user29", "/user5/repo4/wiki", true) + }) + t.Run("other user", func(t *testing.T) { + canEditWiki(t, "user2", "/user5/repo4/wiki", false) + }) + }) + + t.Run("globally writable", func(t *testing.T) { + session := loginUser(t, "user5") + csrf := GetCSRF(t, session, "/user5/repo4/settings/units") + req := NewRequestWithValues(t, "POST", "/user5/repo4/settings/units", map[string]string{ + "_csrf": csrf, + "enable_wiki": "on", + "globally_writeable_wiki": "on", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + t.Run("anonymous", func(t *testing.T) { + canEditWiki(t, "", "/user5/repo4/wiki", false) + }) + t.Run("owner", func(t *testing.T) { + canEditWiki(t, "user5", "/user5/repo4/wiki", true) + }) + t.Run("collaborator", func(t *testing.T) { + canEditWiki(t, "user4", "/user5/repo4/wiki", true) + canEditWiki(t, "user29", "/user5/repo4/wiki", true) + }) + t.Run("other user", func(t *testing.T) { + canEditWiki(t, "user2", "/user5/repo4/wiki", true) + }) + }) +}