Merge pull request 'Allow changing global wiki editability via the API' (#3276) from algernon/forgejo:let-the-api-control-your-wiki-editability into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3276 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
This commit is contained in:
commit
a003691c7b
5 changed files with 97 additions and 4 deletions
|
@ -89,6 +89,7 @@ type Repository struct {
|
||||||
HasWiki bool `json:"has_wiki"`
|
HasWiki bool `json:"has_wiki"`
|
||||||
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
|
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
|
||||||
WikiBranch string `json:"wiki_branch,omitempty"`
|
WikiBranch string `json:"wiki_branch,omitempty"`
|
||||||
|
GloballyEditableWiki bool `json:"globally_editable_wiki"`
|
||||||
HasPullRequests bool `json:"has_pull_requests"`
|
HasPullRequests bool `json:"has_pull_requests"`
|
||||||
HasProjects bool `json:"has_projects"`
|
HasProjects bool `json:"has_projects"`
|
||||||
HasReleases bool `json:"has_releases"`
|
HasReleases bool `json:"has_releases"`
|
||||||
|
@ -185,6 +186,8 @@ type EditRepoOption struct {
|
||||||
HasWiki *bool `json:"has_wiki,omitempty"`
|
HasWiki *bool `json:"has_wiki,omitempty"`
|
||||||
// set this structure to use external wiki instead of internal
|
// set this structure to use external wiki instead of internal
|
||||||
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
|
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
|
||||||
|
// set the globally editable state of the wiki
|
||||||
|
GloballyEditableWiki *bool `json:"globally_editable_wiki,omitempty"`
|
||||||
// sets the default branch for this repository.
|
// sets the default branch for this repository.
|
||||||
DefaultBranch *string `json:"default_branch,omitempty"`
|
DefaultBranch *string `json:"default_branch,omitempty"`
|
||||||
// sets the branch used for this repository's wiki.
|
// sets the branch used for this repository's wiki.
|
||||||
|
|
|
@ -845,6 +845,15 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
|
||||||
newHasWiki = *opts.HasWiki
|
newHasWiki = *opts.HasWiki
|
||||||
}
|
}
|
||||||
if currHasWiki || newHasWiki {
|
if currHasWiki || newHasWiki {
|
||||||
|
wikiPermissions := repo.MustGetUnit(ctx, unit_model.TypeWiki).DefaultPermissions
|
||||||
|
if opts.GloballyEditableWiki != nil {
|
||||||
|
if *opts.GloballyEditableWiki {
|
||||||
|
wikiPermissions = repo_model.UnitAccessModeWrite
|
||||||
|
} else {
|
||||||
|
wikiPermissions = repo_model.UnitAccessModeRead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if newHasWiki && opts.ExternalWiki != nil && !unit_model.TypeExternalWiki.UnitGlobalDisabled() {
|
if newHasWiki && opts.ExternalWiki != nil && !unit_model.TypeExternalWiki.UnitGlobalDisabled() {
|
||||||
// Check that values are valid
|
// Check that values are valid
|
||||||
if !validation.IsValidExternalURL(opts.ExternalWiki.ExternalWikiURL) {
|
if !validation.IsValidExternalURL(opts.ExternalWiki.ExternalWikiURL) {
|
||||||
|
@ -867,6 +876,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
|
||||||
RepoID: repo.ID,
|
RepoID: repo.ID,
|
||||||
Type: unit_model.TypeWiki,
|
Type: unit_model.TypeWiki,
|
||||||
Config: config,
|
Config: config,
|
||||||
|
DefaultPermissions: wikiPermissions,
|
||||||
})
|
})
|
||||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalWiki)
|
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalWiki)
|
||||||
} else if !newHasWiki {
|
} else if !newHasWiki {
|
||||||
|
@ -876,6 +886,14 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
|
||||||
if !unit_model.TypeWiki.UnitGlobalDisabled() {
|
if !unit_model.TypeWiki.UnitGlobalDisabled() {
|
||||||
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeWiki)
|
deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeWiki)
|
||||||
}
|
}
|
||||||
|
} else if *opts.GloballyEditableWiki {
|
||||||
|
config := &repo_model.UnitConfig{}
|
||||||
|
units = append(units, repo_model.RepoUnit{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Type: unit_model.TypeWiki,
|
||||||
|
Config: config,
|
||||||
|
DefaultPermissions: wikiPermissions,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,9 +77,13 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hasWiki := false
|
hasWiki := false
|
||||||
|
globallyEditableWiki := false
|
||||||
var externalWiki *api.ExternalWiki
|
var externalWiki *api.ExternalWiki
|
||||||
if _, err := repo.GetUnit(ctx, unit_model.TypeWiki); err == nil {
|
if wikiUnit, err := repo.GetUnit(ctx, unit_model.TypeWiki); err == nil {
|
||||||
hasWiki = true
|
hasWiki = true
|
||||||
|
if wikiUnit.DefaultPermissions == repo_model.UnitAccessModeWrite {
|
||||||
|
globallyEditableWiki = true
|
||||||
|
}
|
||||||
} else if unit, err := repo.GetUnit(ctx, unit_model.TypeExternalWiki); err == nil {
|
} else if unit, err := repo.GetUnit(ctx, unit_model.TypeExternalWiki); err == nil {
|
||||||
hasWiki = true
|
hasWiki = true
|
||||||
config := unit.ExternalWikiConfig()
|
config := unit.ExternalWikiConfig()
|
||||||
|
@ -211,6 +215,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||||
InternalTracker: internalTracker,
|
InternalTracker: internalTracker,
|
||||||
HasWiki: hasWiki,
|
HasWiki: hasWiki,
|
||||||
WikiBranch: repo.WikiBranch,
|
WikiBranch: repo.WikiBranch,
|
||||||
|
GloballyEditableWiki: globallyEditableWiki,
|
||||||
HasProjects: hasProjects,
|
HasProjects: hasProjects,
|
||||||
HasReleases: hasReleases,
|
HasReleases: hasReleases,
|
||||||
HasPackages: hasPackages,
|
HasPackages: hasPackages,
|
||||||
|
|
9
templates/swagger/v1_json.tmpl
generated
9
templates/swagger/v1_json.tmpl
generated
|
@ -20835,6 +20835,11 @@
|
||||||
"external_wiki": {
|
"external_wiki": {
|
||||||
"$ref": "#/definitions/ExternalWiki"
|
"$ref": "#/definitions/ExternalWiki"
|
||||||
},
|
},
|
||||||
|
"globally_editable_wiki": {
|
||||||
|
"description": "set the globally editable state of the wiki",
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "GloballyEditableWiki"
|
||||||
|
},
|
||||||
"has_actions": {
|
"has_actions": {
|
||||||
"description": "either `true` to enable actions unit, or `false` to disable them.",
|
"description": "either `true` to enable actions unit, or `false` to disable them.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
@ -23749,6 +23754,10 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"x-go-name": "FullName"
|
"x-go-name": "FullName"
|
||||||
},
|
},
|
||||||
|
"globally_editable_wiki": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "GloballyEditableWiki"
|
||||||
|
},
|
||||||
"has_actions": {
|
"has_actions": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"x-go-name": "HasActions"
|
"x-go-name": "HasActions"
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
unit_model "code.gitea.io/gitea/models/unit"
|
unit_model "code.gitea.io/gitea/models/unit"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
repo_service "code.gitea.io/gitea/services/repository"
|
repo_service "code.gitea.io/gitea/services/repository"
|
||||||
"code.gitea.io/gitea/tests"
|
"code.gitea.io/gitea/tests"
|
||||||
|
@ -286,6 +287,63 @@ func TestAPIEditOtherWikiPage(t *testing.T) {
|
||||||
testCreateWiki(http.StatusCreated)
|
testCreateWiki(http.StatusCreated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAPISetWikiGlobalEditability(t *testing.T) {
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "user2"})
|
||||||
|
session := loginUser(t, user.Name)
|
||||||
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
|
// Create a new repository for testing purposes
|
||||||
|
repo, _, f := CreateDeclarativeRepo(t, user, "", []unit_model.Type{
|
||||||
|
unit_model.TypeCode,
|
||||||
|
unit_model.TypeWiki,
|
||||||
|
}, nil, nil)
|
||||||
|
defer f()
|
||||||
|
urlStr := fmt.Sprintf("/api/v1/repos/%s", repo.FullName())
|
||||||
|
|
||||||
|
assertGlobalEditability := func(t *testing.T, editability bool) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
req := NewRequest(t, "GET", urlStr)
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
var opts api.Repository
|
||||||
|
DecodeJSON(t, resp, &opts)
|
||||||
|
|
||||||
|
assert.Equal(t, opts.GloballyEditableWiki, editability)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("api includes GloballyEditableWiki", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
assertGlobalEditability(t, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("api can turn on GloballyEditableWiki", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
globallyEditable := true
|
||||||
|
req := NewRequestWithJSON(t, "PATCH", urlStr, &api.EditRepoOption{
|
||||||
|
GloballyEditableWiki: &globallyEditable,
|
||||||
|
}).AddTokenAuth(token)
|
||||||
|
MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
assertGlobalEditability(t, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("disabling the wiki disables GloballyEditableWiki", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
hasWiki := false
|
||||||
|
req := NewRequestWithJSON(t, "PATCH", urlStr, &api.EditRepoOption{
|
||||||
|
HasWiki: &hasWiki,
|
||||||
|
}).AddTokenAuth(token)
|
||||||
|
MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
assertGlobalEditability(t, false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestAPIListPageRevisions(t *testing.T) {
|
func TestAPIListPageRevisions(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
username := "user2"
|
username := "user2"
|
||||||
|
|
Loading…
Reference in a new issue