diff --git a/models/repo/repo_unit.go b/models/repo/repo_unit.go index 7ae9ad287c..4c3b212f7b 100644 --- a/models/repo/repo_unit.go +++ b/models/repo/repo_unit.go @@ -176,6 +176,8 @@ const ( ActionsTokenPermissionModePermissive ActionsTokenPermissionMode = "permissive" // ActionsTokenPermissionModeRestricted - read access by default ActionsTokenPermissionModeRestricted ActionsTokenPermissionMode = "restricted" + // ActionsTokenPermissionModeCustom - user-defined permissions + ActionsTokenPermissionModeCustom ActionsTokenPermissionMode = "custom" ) // ActionsTokenPermissions defines the permissions for different repository units @@ -194,6 +196,46 @@ type ActionsTokenPermissions struct { Wiki perm.AccessMode `json:"wiki"` } +// HasRead checks if the permission has read access for the given scope +func (p ActionsTokenPermissions) HasRead(scope string) bool { + var mode perm.AccessMode + switch scope { + case "actions": + mode = p.Actions + case "contents": + mode = p.Contents + case "issues": + mode = p.Issues + case "packages": + mode = p.Packages + case "pull_requests": + mode = p.PullRequests + case "wiki": + mode = p.Wiki + } + return mode >= perm.AccessModeRead +} + +// HasWrite checks if the permission has write access for the given scope +func (p ActionsTokenPermissions) HasWrite(scope string) bool { + var mode perm.AccessMode + switch scope { + case "actions": + mode = p.Actions + case "contents": + mode = p.Contents + case "issues": + mode = p.Issues + case "packages": + mode = p.Packages + case "pull_requests": + mode = p.PullRequests + case "wiki": + mode = p.Wiki + } + return mode >= perm.AccessModeWrite +} + // DefaultActionsTokenPermissions returns the default permissions for permissive mode func DefaultActionsTokenPermissions(mode ActionsTokenPermissionMode) ActionsTokenPermissions { if mode == ActionsTokenPermissionModeRestricted { diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 50609582ae..1780f19e52 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3957,6 +3957,9 @@ general.token_permissions.access_none = No access general.token_permissions.update_success = Token permissions updated successfully. general.token_permissions.cross_repo = Cross-Repository Access general.token_permissions.cross_repo_desc = Allow workflows in this organization to access other repositories within the same organization. +general.token_permissions.custom = Custom permissions +general.token_permissions.custom.description = Configure permissions for each scope individually. +general.token_permissions.individual = Individual Permissions [projects] deleted.display_name = Deleted Project diff --git a/routers/web/org/setting/actions.go b/routers/web/org/setting/actions.go index 44d014b20c..1b35681889 100644 --- a/routers/web/org/setting/actions.go +++ b/routers/web/org/setting/actions.go @@ -7,6 +7,7 @@ import ( "net/http" actions_model "code.gitea.io/gitea/models/actions" + "code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/services/context" @@ -32,6 +33,8 @@ func ActionsGeneral(ctx *context.Context) { ctx.Data["TokenPermissionMode"] = actionsCfg.GetTokenPermissionMode() ctx.Data["TokenPermissionModePermissive"] = repo_model.ActionsTokenPermissionModePermissive ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted + ctx.Data["TokenPermissionModeCustom"] = repo_model.ActionsTokenPermissionModeCustom + ctx.Data["DefaultTokenPermissions"] = actionsCfg.GetEffectiveTokenPermissions(false) ctx.Data["AllowCrossRepoAccess"] = actionsCfg.AllowCrossRepoAccess @@ -52,10 +55,35 @@ func ActionsGeneralPost(ctx *context.Context) { // Update Token Permission Mode permissionMode := repo_model.ActionsTokenPermissionMode(ctx.FormString("token_permission_mode")) - if permissionMode == repo_model.ActionsTokenPermissionModeRestricted || permissionMode == repo_model.ActionsTokenPermissionModePermissive { + if permissionMode == repo_model.ActionsTokenPermissionModeRestricted || + permissionMode == repo_model.ActionsTokenPermissionModePermissive || + permissionMode == repo_model.ActionsTokenPermissionModeCustom { actionsCfg.TokenPermissionMode = permissionMode } + if actionsCfg.TokenPermissionMode == repo_model.ActionsTokenPermissionModeCustom { + parsePerm := func(name string) perm.AccessMode { + if ctx.FormBool(name + "_write") { + return perm.AccessModeWrite + } + if ctx.FormBool(name + "_read") { + return perm.AccessModeRead + } + return perm.AccessModeNone + } + + actionsCfg.DefaultTokenPermissions = &repo_model.ActionsTokenPermissions{ + Actions: parsePerm("actions"), + Contents: parsePerm("contents"), + Issues: parsePerm("issues"), + Packages: parsePerm("packages"), + PullRequests: parsePerm("pull_requests"), + Wiki: parsePerm("wiki"), + } + } else { + actionsCfg.DefaultTokenPermissions = nil + } + // Update Cross-Repo Access actionsCfg.AllowCrossRepoAccess = ctx.FormBool("allow_cross_repo_access") diff --git a/routers/web/repo/setting/actions.go b/routers/web/repo/setting/actions.go index 29e525665b..79875a00eb 100644 --- a/routers/web/repo/setting/actions.go +++ b/routers/web/repo/setting/actions.go @@ -8,6 +8,7 @@ import ( "net/http" "strings" + "code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" unit_model "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" @@ -40,6 +41,8 @@ func ActionsGeneralSettings(ctx *context.Context) { ctx.Data["TokenPermissionMode"] = actionsCfg.GetTokenPermissionMode() ctx.Data["TokenPermissionModePermissive"] = repo_model.ActionsTokenPermissionModePermissive ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted + ctx.Data["TokenPermissionModeCustom"] = repo_model.ActionsTokenPermissionModeCustom + ctx.Data["DefaultTokenPermissions"] = actionsCfg.GetEffectiveTokenPermissions(false) if ctx.Repo.Repository.IsPrivate { collaborativeOwnerIDs := actionsCfg.CollaborativeOwnerIDs @@ -141,7 +144,9 @@ func UpdateTokenPermissions(ctx *context.Context) { // Update permission mode permissionMode := repo_model.ActionsTokenPermissionMode(ctx.FormString("token_permission_mode")) - if permissionMode == repo_model.ActionsTokenPermissionModeRestricted || permissionMode == repo_model.ActionsTokenPermissionModePermissive { + if permissionMode == repo_model.ActionsTokenPermissionModeRestricted || + permissionMode == repo_model.ActionsTokenPermissionModePermissive || + permissionMode == repo_model.ActionsTokenPermissionModeCustom { actionsCfg.TokenPermissionMode = permissionMode } else { ctx.Flash.Error("Invalid token permission mode") @@ -149,6 +154,29 @@ func UpdateTokenPermissions(ctx *context.Context) { return } + if actionsCfg.TokenPermissionMode == repo_model.ActionsTokenPermissionModeCustom { + parsePerm := func(name string) perm.AccessMode { + if ctx.FormBool(name + "_write") { + return perm.AccessModeWrite + } + if ctx.FormBool(name + "_read") { + return perm.AccessModeRead + } + return perm.AccessModeNone + } + + actionsCfg.DefaultTokenPermissions = &repo_model.ActionsTokenPermissions{ + Actions: parsePerm("actions"), + Contents: parsePerm("contents"), + Issues: parsePerm("issues"), + Packages: parsePerm("packages"), + PullRequests: parsePerm("pull_requests"), + Wiki: parsePerm("wiki"), + } + } else { + actionsCfg.DefaultTokenPermissions = nil + } + if err := repo_model.UpdateRepoUnit(ctx, actionsUnit); err != nil { ctx.ServerError("UpdateRepoUnit", err) return diff --git a/templates/org/settings/actions_general.tmpl b/templates/org/settings/actions_general.tmpl index 1057d8d8e1..b66c8121e2 100644 --- a/templates/org/settings/actions_general.tmpl +++ b/templates/org/settings/actions_general.tmpl @@ -25,6 +25,103 @@
{{.locale.Tr "actions.general.token_permissions.restricted.description"}}
+{{.locale.Tr "actions.general.token_permissions.custom.description"}}
+