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]>
192 lines
6.1 KiB
Go
192 lines
6.1 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package setting
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
|
|
"github.com/hanzoai/git/models/actions"
|
|
repo_model "github.com/hanzoai/git/models/repo"
|
|
unit_model "github.com/hanzoai/git/models/unit"
|
|
user_model "github.com/hanzoai/git/models/user"
|
|
"github.com/hanzoai/git/modules/templates"
|
|
"github.com/hanzoai/git/modules/util"
|
|
shared_actions "github.com/hanzoai/git/routers/web/shared/actions"
|
|
"github.com/hanzoai/git/services/context"
|
|
repo_service "github.com/hanzoai/git/services/repository"
|
|
)
|
|
|
|
const tplRepoActionsGeneralSettings templates.TplName = "repo/settings/actions"
|
|
|
|
func ActionsGeneralSettings(ctx *context.Context) {
|
|
ctx.Data["Title"] = ctx.Tr("actions.general")
|
|
ctx.Data["PageType"] = "general"
|
|
ctx.Data["PageIsActionsSettingsGeneral"] = true
|
|
|
|
actionsUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeActions)
|
|
if err != nil && !repo_model.IsErrUnitTypeNotExist(err) {
|
|
ctx.ServerError("GetUnit", err)
|
|
return
|
|
}
|
|
if actionsUnit == nil { // no actions unit
|
|
ctx.HTML(http.StatusOK, tplRepoActionsGeneralSettings)
|
|
return
|
|
}
|
|
|
|
actionsCfg := actionsUnit.ActionsConfig()
|
|
|
|
// Token permission settings
|
|
ctx.Data["TokenPermissionModePermissive"] = repo_model.ActionsTokenPermissionModePermissive
|
|
ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted
|
|
|
|
// Follow owner config (only for repos in orgs)
|
|
ctx.Data["OverrideOwnerConfig"] = actionsCfg.OverrideOwnerConfig
|
|
if actionsCfg.OverrideOwnerConfig {
|
|
ctx.Data["MaxTokenPermissions"] = actionsCfg.GetMaxTokenPermissions()
|
|
ctx.Data["TokenPermissionMode"] = actionsCfg.TokenPermissionMode
|
|
ctx.Data["EnableMaxTokenPermissions"] = actionsCfg.MaxTokenPermissions != nil
|
|
} else {
|
|
ownerActionsConfig, err := actions.GetOwnerActionsConfig(ctx, ctx.Repo.Repository.OwnerID)
|
|
if err != nil {
|
|
ctx.ServerError("GetOwnerActionsConfig", err)
|
|
return
|
|
}
|
|
ctx.Data["MaxTokenPermissions"] = ownerActionsConfig.GetMaxTokenPermissions()
|
|
ctx.Data["TokenPermissionMode"] = ownerActionsConfig.TokenPermissionMode
|
|
ctx.Data["EnableMaxTokenPermissions"] = ownerActionsConfig.MaxTokenPermissions != nil
|
|
}
|
|
|
|
if ctx.Repo.Repository.IsPrivate {
|
|
collaborativeOwnerIDs := actionsCfg.CollaborativeOwnerIDs
|
|
collaborativeOwners, err := user_model.GetUsersByIDs(ctx, collaborativeOwnerIDs)
|
|
if err != nil {
|
|
ctx.ServerError("GetUsersByIDs", err)
|
|
return
|
|
}
|
|
ctx.Data["CollaborativeOwners"] = collaborativeOwners
|
|
}
|
|
|
|
ctx.HTML(http.StatusOK, tplRepoActionsGeneralSettings)
|
|
}
|
|
|
|
func ActionsUnitPost(ctx *context.Context) {
|
|
redirectURL := ctx.Repo.RepoLink + "/settings/actions/general"
|
|
enableActionsUnit := ctx.FormBool("enable_actions")
|
|
repo := ctx.Repo.Repository
|
|
|
|
var err error
|
|
if enableActionsUnit && !unit_model.TypeActions.UnitGlobalDisabled() {
|
|
err = repo_service.UpdateRepositoryUnits(ctx, repo, []repo_model.RepoUnit{newRepoUnit(repo, unit_model.TypeActions, nil)}, nil)
|
|
} else if !unit_model.TypeActions.UnitGlobalDisabled() {
|
|
err = repo_service.UpdateRepositoryUnits(ctx, repo, nil, []unit_model.Type{unit_model.TypeActions})
|
|
}
|
|
|
|
if err != nil {
|
|
ctx.ServerError("UpdateRepositoryUnits", err)
|
|
return
|
|
}
|
|
|
|
ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
|
|
ctx.Redirect(redirectURL)
|
|
}
|
|
|
|
func AddCollaborativeOwner(ctx *context.Context) {
|
|
collUser, err := user_model.GetUserByName(ctx, ctx.FormString("collaborative_owner"))
|
|
if err != nil {
|
|
if errors.Is(err, util.ErrNotExist) {
|
|
ctx.JSONError(ctx.Tr("form.user_not_exist"))
|
|
} else {
|
|
ctx.ServerError("GetUserByName", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
actionsUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeActions)
|
|
if err != nil {
|
|
ctx.ServerError("GetUnit", err)
|
|
return
|
|
}
|
|
actionsCfg := actionsUnit.ActionsConfig()
|
|
actionsCfg.AddCollaborativeOwner(collUser.ID)
|
|
if err := repo_model.UpdateRepoUnitConfig(ctx, actionsUnit); err != nil {
|
|
ctx.ServerError("UpdateRepoUnitConfig", err)
|
|
return
|
|
}
|
|
|
|
ctx.JSONOK()
|
|
}
|
|
|
|
func DeleteCollaborativeOwner(ctx *context.Context) {
|
|
ownerID := ctx.FormInt64("id")
|
|
|
|
actionsUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeActions)
|
|
if err != nil {
|
|
ctx.ServerError("GetUnit", err)
|
|
return
|
|
}
|
|
actionsCfg := actionsUnit.ActionsConfig()
|
|
if !actionsCfg.IsCollaborativeOwner(ownerID) {
|
|
ctx.Flash.Error(ctx.Tr("actions.general.collaborative_owner_not_exist"))
|
|
ctx.JSONErrorNotFound()
|
|
return
|
|
}
|
|
actionsCfg.RemoveCollaborativeOwner(ownerID)
|
|
if err := repo_model.UpdateRepoUnitConfig(ctx, actionsUnit); err != nil {
|
|
ctx.ServerError("UpdateRepoUnitConfig", err)
|
|
return
|
|
}
|
|
|
|
ctx.JSONOK()
|
|
}
|
|
|
|
// UpdateTokenPermissions updates the token permission settings for the repository
|
|
func UpdateTokenPermissions(ctx *context.Context) {
|
|
redirectURL := ctx.Repo.RepoLink + "/settings/actions/general"
|
|
|
|
actionsUnit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeActions)
|
|
if err != nil {
|
|
ctx.ServerError("GetUnit", err)
|
|
return
|
|
}
|
|
|
|
actionsCfg := actionsUnit.ActionsConfig()
|
|
|
|
// Update Override Owner Config (for repos in orgs)
|
|
// If checked, it means we WANT to override (opt-out of following)
|
|
actionsCfg.OverrideOwnerConfig = ctx.FormBool("override_owner_config")
|
|
|
|
// Update permission mode (only if overriding owner config)
|
|
shouldUpdate := actionsCfg.OverrideOwnerConfig
|
|
|
|
if shouldUpdate {
|
|
permissionMode, permissionModeValid := util.EnumValue(repo_model.ActionsTokenPermissionMode(ctx.FormString("token_permission_mode")))
|
|
if !permissionModeValid {
|
|
ctx.Flash.Error("Invalid token permission mode")
|
|
ctx.Redirect(redirectURL)
|
|
return
|
|
}
|
|
actionsCfg.TokenPermissionMode = permissionMode
|
|
}
|
|
|
|
// Update Maximum Permissions (radio buttons: none/read/write)
|
|
enableMaxPermissions := ctx.FormBool("enable_max_permissions")
|
|
if shouldUpdate {
|
|
if enableMaxPermissions {
|
|
actionsCfg.MaxTokenPermissions = shared_actions.ParseMaxTokenPermissions(ctx)
|
|
} else {
|
|
// If not enabled, ensure any sent permissions are ignored and set to nil
|
|
actionsCfg.MaxTokenPermissions = nil
|
|
}
|
|
}
|
|
|
|
if err := repo_model.UpdateRepoUnitConfig(ctx, actionsUnit); err != nil {
|
|
ctx.ServerError("UpdateRepoUnitConfig", err)
|
|
return
|
|
}
|
|
|
|
ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
|
|
ctx.Redirect(redirectURL)
|
|
}
|