diff options
Diffstat (limited to 'routers/web/repo/setting/public_access.go')
-rw-r--r-- | routers/web/repo/setting/public_access.go | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/routers/web/repo/setting/public_access.go b/routers/web/repo/setting/public_access.go new file mode 100644 index 0000000000..368d34294a --- /dev/null +++ b/routers/web/repo/setting/public_access.go @@ -0,0 +1,155 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package setting + +import ( + "net/http" + "slices" + "strconv" + + "code.gitea.io/gitea/models/perm" + "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/templates" + "code.gitea.io/gitea/services/context" +) + +const tplRepoSettingsPublicAccess templates.TplName = "repo/settings/public_access" + +func parsePublicAccessMode(permission string, allowed []string) (ret struct { + AnonymousAccessMode, EveryoneAccessMode perm.AccessMode +}, +) { + ret.AnonymousAccessMode = perm.AccessModeNone + ret.EveryoneAccessMode = perm.AccessModeNone + + // if site admin forces repositories to be private, then do not allow any other access mode, + // otherwise the "force private" setting would be bypassed + if setting.Repository.ForcePrivate { + return ret + } + if !slices.Contains(allowed, permission) { + return ret + } + switch permission { + case paAnonymousRead: + ret.AnonymousAccessMode = perm.AccessModeRead + case paEveryoneRead: + ret.EveryoneAccessMode = perm.AccessModeRead + case paEveryoneWrite: + ret.EveryoneAccessMode = perm.AccessModeWrite + } + return ret +} + +const ( + paNotSet = "not-set" + paAnonymousRead = "anonymous-read" + paEveryoneRead = "everyone-read" + paEveryoneWrite = "everyone-write" +) + +type repoUnitPublicAccess struct { + UnitType unit.Type + FormKey string + DisplayName string + PublicAccessTypes []string + UnitPublicAccess string +} + +func repoUnitPublicAccesses(ctx *context.Context) []*repoUnitPublicAccess { + accesses := []*repoUnitPublicAccess{ + { + UnitType: unit.TypeCode, + DisplayName: ctx.Locale.TrString("repo.code"), + PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead}, + }, + { + UnitType: unit.TypeIssues, + DisplayName: ctx.Locale.TrString("issues"), + PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead}, + }, + { + UnitType: unit.TypePullRequests, + DisplayName: ctx.Locale.TrString("pull_requests"), + PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead}, + }, + { + UnitType: unit.TypeReleases, + DisplayName: ctx.Locale.TrString("repo.releases"), + PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead}, + }, + { + UnitType: unit.TypeWiki, + DisplayName: ctx.Locale.TrString("repo.wiki"), + PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead, paEveryoneWrite}, + }, + { + UnitType: unit.TypeProjects, + DisplayName: ctx.Locale.TrString("repo.projects"), + PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead}, + }, + { + UnitType: unit.TypePackages, + DisplayName: ctx.Locale.TrString("repo.packages"), + PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead}, + }, + { + UnitType: unit.TypeActions, + DisplayName: ctx.Locale.TrString("repo.actions"), + PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead}, + }, + } + for _, ua := range accesses { + ua.FormKey = "repo-unit-access-" + strconv.Itoa(int(ua.UnitType)) + for _, u := range ctx.Repo.Repository.Units { + if u.Type == ua.UnitType { + ua.UnitPublicAccess = paNotSet + switch { + case u.EveryoneAccessMode == perm.AccessModeWrite: + ua.UnitPublicAccess = paEveryoneWrite + case u.EveryoneAccessMode == perm.AccessModeRead: + ua.UnitPublicAccess = paEveryoneRead + case u.AnonymousAccessMode == perm.AccessModeRead: + ua.UnitPublicAccess = paAnonymousRead + } + break + } + } + } + return slices.DeleteFunc(accesses, func(ua *repoUnitPublicAccess) bool { + return ua.UnitPublicAccess == "" + }) +} + +func PublicAccess(ctx *context.Context) { + ctx.Data["PageIsSettingsPublicAccess"] = true + ctx.Data["RepoUnitPublicAccesses"] = repoUnitPublicAccesses(ctx) + ctx.Data["GlobalForcePrivate"] = setting.Repository.ForcePrivate + if setting.Repository.ForcePrivate { + ctx.Flash.Error(ctx.Tr("form.repository_force_private"), true) + } + ctx.HTML(http.StatusOK, tplRepoSettingsPublicAccess) +} + +func PublicAccessPost(ctx *context.Context) { + accesses := repoUnitPublicAccesses(ctx) + for _, ua := range accesses { + formVal := ctx.FormString(ua.FormKey) + parsed := parsePublicAccessMode(formVal, ua.PublicAccessTypes) + err := repo.UpdateRepoUnitPublicAccess(ctx, &repo.RepoUnit{ + RepoID: ctx.Repo.Repository.ID, + Type: ua.UnitType, + AnonymousAccessMode: parsed.AnonymousAccessMode, + EveryoneAccessMode: parsed.EveryoneAccessMode, + }) + if err != nil { + ctx.ServerError("UpdateRepoUnitPublicAccess", err) + return + } + } + ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success")) + ctx.Redirect(ctx.Repo.Repository.Link() + "/settings/public_access") +} |