diff --git a/modules/structs/repo.go b/modules/structs/repo.go index f6cc9803a4..1158160b53 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -89,6 +89,7 @@ type Repository struct { HasWiki bool `json:"has_wiki"` ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"` WikiBranch string `json:"wiki_branch,omitempty"` + GloballyEditableWiki bool `json:"globally_editable_wiki"` HasPullRequests bool `json:"has_pull_requests"` HasProjects bool `json:"has_projects"` HasReleases bool `json:"has_releases"` @@ -185,6 +186,8 @@ type EditRepoOption struct { HasWiki *bool `json:"has_wiki,omitempty"` // set this structure to use external wiki instead of internal 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. DefaultBranch *string `json:"default_branch,omitempty"` // sets the branch used for this repository's wiki. diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 562c3eb64c..6692633fab 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -845,6 +845,15 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { newHasWiki = *opts.HasWiki } 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() { // Check that values are valid if !validation.IsValidExternalURL(opts.ExternalWiki.ExternalWikiURL) { @@ -864,9 +873,10 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { } else if newHasWiki && opts.ExternalWiki == nil && !unit_model.TypeWiki.UnitGlobalDisabled() { config := &repo_model.UnitConfig{} units = append(units, repo_model.RepoUnit{ - RepoID: repo.ID, - Type: unit_model.TypeWiki, - Config: config, + RepoID: repo.ID, + Type: unit_model.TypeWiki, + Config: config, + DefaultPermissions: wikiPermissions, }) deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeExternalWiki) } else if !newHasWiki { @@ -876,6 +886,14 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { if !unit_model.TypeWiki.UnitGlobalDisabled() { 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, + }) } } diff --git a/services/convert/repository.go b/services/convert/repository.go index 466d19d563..fcd0824e45 100644 --- a/services/convert/repository.go +++ b/services/convert/repository.go @@ -77,9 +77,13 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR } } hasWiki := false + globallyEditableWiki := false 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 + if wikiUnit.DefaultPermissions == repo_model.UnitAccessModeWrite { + globallyEditableWiki = true + } } else if unit, err := repo.GetUnit(ctx, unit_model.TypeExternalWiki); err == nil { hasWiki = true config := unit.ExternalWikiConfig() @@ -211,6 +215,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR InternalTracker: internalTracker, HasWiki: hasWiki, WikiBranch: repo.WikiBranch, + GloballyEditableWiki: globallyEditableWiki, HasProjects: hasProjects, HasReleases: hasReleases, HasPackages: hasPackages, diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 4e4971dfe9..2bec62694f 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -20835,6 +20835,11 @@ "external_wiki": { "$ref": "#/definitions/ExternalWiki" }, + "globally_editable_wiki": { + "description": "set the globally editable state of the wiki", + "type": "boolean", + "x-go-name": "GloballyEditableWiki" + }, "has_actions": { "description": "either `true` to enable actions unit, or `false` to disable them.", "type": "boolean", @@ -23749,6 +23754,10 @@ "type": "string", "x-go-name": "FullName" }, + "globally_editable_wiki": { + "type": "boolean", + "x-go-name": "GloballyEditableWiki" + }, "has_actions": { "type": "boolean", "x-go-name": "HasActions" diff --git a/tests/integration/api_wiki_test.go b/tests/integration/api_wiki_test.go index c61b4a061b..2b71616112 100644 --- a/tests/integration/api_wiki_test.go +++ b/tests/integration/api_wiki_test.go @@ -15,6 +15,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" unit_model "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" api "code.gitea.io/gitea/modules/structs" repo_service "code.gitea.io/gitea/services/repository" "code.gitea.io/gitea/tests" @@ -286,6 +287,63 @@ func TestAPIEditOtherWikiPage(t *testing.T) { 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) { defer tests.PrepareTestEnv(t)() username := "user2"