5eeccecafc
This is largely based on gitea#6312 by @ashimokawa, with updates and fixes by myself, and incorporates the review feedback given in that pull request, and more. What this patch does is add a new "default_permissions" column to the `repo_units` table (defaulting to read permission), adjusts the permission checking code to take this into consideration, and then exposes a setting that lets a repo administrator enable any user on a Forgejo instance to edit the repo's wiki (effectively giving the wiki unit of the repo "write" permissions by default). By default, wikis will remain restricted to collaborators, but with the new setting exposed, they can be turned into globally editable wikis. Fixes Codeberg/Community#28. Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu> (cherry picked from commit 4b744399229f255eb124c22e3969715046043209) (cherry picked from commit 337cf62c1094273ab61fbaab8e7fb41eb6e2e979) (cherry picked from commit b6786fdb3246a3a455b59149943807c1f13a028a) (cherry picked from commit a5d2829a1027afd593fd855a8e2d7d7cd38234b8) [GITEA] Optionally allow anyone to edit Wikis (squash) AddTokenAuth (cherry picked from commit fed50cf72eaaa00ef1f4730f9b12a64a10b66113) (cherry picked from commit 42c55e494e1018a210e54d405c15eec24a0b37c7) (cherry picked from commit e3463bda47ffee4ab57efadfe5094f9401541cfd)
302 lines
8.3 KiB
Go
302 lines
8.3 KiB
Go
// Copyright 2021 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package integration
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"net/http"
|
|
"testing"
|
|
|
|
auth_model "code.gitea.io/gitea/models/auth"
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
unit_model "code.gitea.io/gitea/models/unit"
|
|
"code.gitea.io/gitea/models/unittest"
|
|
api "code.gitea.io/gitea/modules/structs"
|
|
repo_service "code.gitea.io/gitea/services/repository"
|
|
"code.gitea.io/gitea/tests"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestAPIGetWikiPage(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
username := "user2"
|
|
|
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/page/Home", username, "repo1")
|
|
|
|
req := NewRequest(t, "GET", urlStr)
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
var page *api.WikiPage
|
|
DecodeJSON(t, resp, &page)
|
|
|
|
assert.Equal(t, &api.WikiPage{
|
|
WikiPageMetaData: &api.WikiPageMetaData{
|
|
Title: "Home",
|
|
HTMLURL: page.HTMLURL,
|
|
SubURL: "Home",
|
|
LastCommit: &api.WikiCommit{
|
|
ID: "2c54faec6c45d31c1abfaecdab471eac6633738a",
|
|
Author: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "Ethan Koenig",
|
|
Email: "ethantkoenig@gmail.com",
|
|
},
|
|
Date: "2017-11-27T04:31:18Z",
|
|
},
|
|
Committer: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "Ethan Koenig",
|
|
Email: "ethantkoenig@gmail.com",
|
|
},
|
|
Date: "2017-11-27T04:31:18Z",
|
|
},
|
|
Message: "Add Home.md\n",
|
|
},
|
|
},
|
|
ContentBase64: base64.RawStdEncoding.EncodeToString(
|
|
[]byte("# Home page\n\nThis is the home page!\n"),
|
|
),
|
|
CommitCount: 1,
|
|
Sidebar: "",
|
|
Footer: "",
|
|
}, page)
|
|
}
|
|
|
|
func TestAPIListWikiPages(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
username := "user2"
|
|
|
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/pages", username, "repo1")
|
|
|
|
req := NewRequest(t, "GET", urlStr)
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
|
|
var meta []*api.WikiPageMetaData
|
|
DecodeJSON(t, resp, &meta)
|
|
|
|
dummymeta := []*api.WikiPageMetaData{
|
|
{
|
|
Title: "Home",
|
|
HTMLURL: meta[0].HTMLURL,
|
|
SubURL: "Home",
|
|
LastCommit: &api.WikiCommit{
|
|
ID: "2c54faec6c45d31c1abfaecdab471eac6633738a",
|
|
Author: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "Ethan Koenig",
|
|
Email: "ethantkoenig@gmail.com",
|
|
},
|
|
Date: "2017-11-27T04:31:18Z",
|
|
},
|
|
Committer: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "Ethan Koenig",
|
|
Email: "ethantkoenig@gmail.com",
|
|
},
|
|
Date: "2017-11-27T04:31:18Z",
|
|
},
|
|
Message: "Add Home.md\n",
|
|
},
|
|
},
|
|
{
|
|
Title: "Page With Image",
|
|
HTMLURL: meta[1].HTMLURL,
|
|
SubURL: "Page-With-Image",
|
|
LastCommit: &api.WikiCommit{
|
|
ID: "0cf15c3f66ec8384480ed9c3cf87c9e97fbb0ec3",
|
|
Author: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "Gabriel Silva Simões",
|
|
Email: "simoes.sgabriel@gmail.com",
|
|
},
|
|
Date: "2019-01-25T01:41:55Z",
|
|
},
|
|
Committer: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "Gabriel Silva Simões",
|
|
Email: "simoes.sgabriel@gmail.com",
|
|
},
|
|
Date: "2019-01-25T01:41:55Z",
|
|
},
|
|
Message: "Add jpeg.jpg and page with image\n",
|
|
},
|
|
},
|
|
{
|
|
Title: "Page With Spaced Name",
|
|
HTMLURL: meta[2].HTMLURL,
|
|
SubURL: "Page-With-Spaced-Name",
|
|
LastCommit: &api.WikiCommit{
|
|
ID: "c10d10b7e655b3dab1f53176db57c8219a5488d6",
|
|
Author: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "Gabriel Silva Simões",
|
|
Email: "simoes.sgabriel@gmail.com",
|
|
},
|
|
Date: "2019-01-25T01:39:51Z",
|
|
},
|
|
Committer: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "Gabriel Silva Simões",
|
|
Email: "simoes.sgabriel@gmail.com",
|
|
},
|
|
Date: "2019-01-25T01:39:51Z",
|
|
},
|
|
Message: "Add page with spaced name\n",
|
|
},
|
|
},
|
|
{
|
|
Title: "Unescaped File",
|
|
HTMLURL: meta[3].HTMLURL,
|
|
SubURL: "Unescaped-File",
|
|
LastCommit: &api.WikiCommit{
|
|
ID: "0dca5bd9b5d7ef937710e056f575e86c0184ba85",
|
|
Author: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "6543",
|
|
Email: "6543@obermui.de",
|
|
},
|
|
Date: "2021-07-19T16:42:46Z",
|
|
},
|
|
Committer: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "6543",
|
|
Email: "6543@obermui.de",
|
|
},
|
|
Date: "2021-07-19T16:42:46Z",
|
|
},
|
|
Message: "add unescaped file\n",
|
|
},
|
|
},
|
|
}
|
|
|
|
assert.Equal(t, dummymeta, meta)
|
|
}
|
|
|
|
func TestAPINewWikiPage(t *testing.T) {
|
|
for _, title := range []string{
|
|
"New page",
|
|
"&&&&",
|
|
} {
|
|
defer tests.PrepareTestEnv(t)()
|
|
username := "user2"
|
|
session := loginUser(t, username)
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/new", username, "repo1")
|
|
|
|
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateWikiPageOptions{
|
|
Title: title,
|
|
ContentBase64: base64.StdEncoding.EncodeToString([]byte("Wiki page content for API unit tests")),
|
|
Message: "",
|
|
}).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusCreated)
|
|
}
|
|
}
|
|
|
|
func TestAPIEditWikiPage(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
username := "user2"
|
|
session := loginUser(t, username)
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/page/Page-With-Spaced-Name", username, "repo1")
|
|
|
|
req := NewRequestWithJSON(t, "PATCH", urlStr, &api.CreateWikiPageOptions{
|
|
Title: "edited title",
|
|
ContentBase64: base64.StdEncoding.EncodeToString([]byte("Edited wiki page content for API unit tests")),
|
|
Message: "",
|
|
}).AddTokenAuth(token)
|
|
MakeRequest(t, req, http.StatusOK)
|
|
}
|
|
|
|
func TestAPIEditOtherWikiPage(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
|
|
// (drive-by-user) user, session, and token for a drive-by wiki editor
|
|
username := "drive-by-user"
|
|
req := NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
|
|
"user_name": username,
|
|
"email": "drive-by@example.com",
|
|
"password": "examplePassword!1",
|
|
"retype": "examplePassword!1",
|
|
})
|
|
MakeRequest(t, req, http.StatusSeeOther)
|
|
session := loginUserWithPassword(t, username, "examplePassword!1")
|
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
|
|
|
// (user2) user for the user whose wiki we're going to edit (as drive-by-user)
|
|
otherUsername := "user2"
|
|
|
|
// Creating a new Wiki page on user2's repo as user1 fails
|
|
testCreateWiki := func(expectedStatusCode int) {
|
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/new", otherUsername, "repo1")
|
|
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateWikiPageOptions{
|
|
Title: "Globally Edited Page",
|
|
ContentBase64: base64.StdEncoding.EncodeToString([]byte("Wiki page content for API unit tests")),
|
|
Message: "",
|
|
}).AddTokenAuth(token)
|
|
session.MakeRequest(t, req, expectedStatusCode)
|
|
}
|
|
testCreateWiki(http.StatusForbidden)
|
|
|
|
// Update the repo settings for user2's repo to enable globally writeable wiki
|
|
ctx := context.Background()
|
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
|
var units []repo_model.RepoUnit
|
|
units = append(units, repo_model.RepoUnit{
|
|
RepoID: repo.ID,
|
|
Type: unit_model.TypeWiki,
|
|
Config: new(repo_model.UnitConfig),
|
|
DefaultPermissions: repo_model.UnitAccessModeWrite,
|
|
})
|
|
err := repo_service.UpdateRepositoryUnits(ctx, repo, units, nil)
|
|
assert.NoError(t, err)
|
|
|
|
// Creating a new Wiki page on user2's repo works now
|
|
testCreateWiki(http.StatusCreated)
|
|
}
|
|
|
|
func TestAPIListPageRevisions(t *testing.T) {
|
|
defer tests.PrepareTestEnv(t)()
|
|
username := "user2"
|
|
|
|
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/revisions/Home", username, "repo1")
|
|
|
|
req := NewRequest(t, "GET", urlStr)
|
|
resp := MakeRequest(t, req, http.StatusOK)
|
|
|
|
var revisions *api.WikiCommitList
|
|
DecodeJSON(t, resp, &revisions)
|
|
|
|
dummyrevisions := &api.WikiCommitList{
|
|
WikiCommits: []*api.WikiCommit{
|
|
{
|
|
ID: "2c54faec6c45d31c1abfaecdab471eac6633738a",
|
|
Author: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "Ethan Koenig",
|
|
Email: "ethantkoenig@gmail.com",
|
|
},
|
|
Date: "2017-11-27T04:31:18Z",
|
|
},
|
|
Committer: &api.CommitUser{
|
|
Identity: api.Identity{
|
|
Name: "Ethan Koenig",
|
|
Email: "ethantkoenig@gmail.com",
|
|
},
|
|
Date: "2017-11-27T04:31:18Z",
|
|
},
|
|
Message: "Add Home.md\n",
|
|
},
|
|
},
|
|
Count: 1,
|
|
}
|
|
|
|
assert.Equal(t, dummyrevisions, revisions)
|
|
}
|