Files
zeekayandHanzo Dev aa87442fdd Record upstream authorship centrally in NOTICE instead of in every file header
Source files keep their SPDX-License-Identifier and Hanzo copyright line; the
Gitea, Gogs and LFS Test Server copyrights they used to repeat now live once in
NOTICE, alongside LICENSE. The header lint accepts any copyright line above the
SPDX line, so it no longer demands an upstream one.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 17:50:35 -07:00

156 lines
4.7 KiB
Go

// Copyright 2026 Hanzo AI, Inc. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import (
"net/http"
"slices"
"strconv"
"github.com/hanzoai/git/models/perm"
"github.com/hanzoai/git/models/repo"
"github.com/hanzoai/git/models/unit"
"github.com/hanzoai/git/modules/setting"
"github.com/hanzoai/git/modules/templates"
"github.com/hanzoai/git/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")
}