1
0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo.git synced 2025-08-03 00:45:22 +02:00

fix: collaborator can edit wiki with write access (#8234)

fixes: #8119, replaces #8135

Bug likely introduced in 5eeccecafc

### 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/<pull request number>.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 <earl-warren@noreply.codeberg.org>
Co-authored-by: oliverpool <git@olivier.pfad.fr>
Co-committed-by: oliverpool <git@olivier.pfad.fr>
This commit is contained in:
oliverpool 2025-06-19 18:35:09 +02:00 committed by Earl Warren
parent 285f66b782
commit 913eaffb8a
2 changed files with 104 additions and 3 deletions

View file

@ -153,11 +153,9 @@ func UnitsPost(ctx *context.Context) {
})
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeWiki)
} else if form.EnableWiki && !form.EnableExternalWiki && !unit_model.TypeWiki.UnitGlobalDisabled() {
var wikiPermissions repo_model.UnitAccessMode
wikiPermissions := repo_model.UnitAccessModeUnset
if form.GloballyWriteableWiki {
wikiPermissions = repo_model.UnitAccessModeWrite
} else {
wikiPermissions = repo_model.UnitAccessModeRead
}
units = append(units, repo_model.RepoUnit{
RepoID: repo.ID,

View file

@ -6,6 +6,8 @@ package integration
import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
auth_model "forgejo.org/models/auth"
@ -113,3 +115,104 @@ func TestWikiTOC(t *testing.T) {
assert.Equal(t, "Helpdesk", htmlDoc.Find(".wiki-content-toc a").Text())
})
}
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)
})
})
}