mirror of
https://github.com/hanzoai/forge.git
synced 2026-10-30 15:00:39 +00:00
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]>
156 lines
4.7 KiB
Go
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")
|
|
}
|