diff --git a/models/perm/access/repo_permission.go b/models/perm/access/repo_permission.go index 3e655d2672..453a90ad5c 100644 --- a/models/perm/access/repo_permission.go +++ b/models/perm/access/repo_permission.go @@ -313,6 +313,7 @@ func GetActionsUserRepoPermission(ctx context.Context, repo *repo_model.Reposito // Get effective token permissions from repository settings effectivePerms := actionsCfg.GetEffectiveTokenPermissions(task.IsForkPullRequest) + effectivePerms = actionsCfg.ClampPermissions(effectivePerms) // Set up per-unit access modes based on configured permissions perm.units = repo.Units diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 1780f19e52..1ea69b6f9c 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3960,6 +3960,8 @@ general.token_permissions.cross_repo_desc = Allow workflows in this organization general.token_permissions.custom = Custom permissions general.token_permissions.custom.description = Configure permissions for each scope individually. general.token_permissions.individual = Individual Permissions +general.token_permissions.maximum = Maximum Permissions +general.token_permissions.maximum.description = Configure the maximum permissions that can be requested by a workflow. [projects] deleted.display_name = Deleted Project diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index 822510dce7..443a14c575 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -103,8 +103,13 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.Context) { } if task.RepoID != packageRepoID { - // Not linked to the running repo. - // Check Org Policy + // 1. Private packages MUST be linked to a repository + if packageRepoID == 0 { + ctx.HTTPError(http.StatusForbidden, "reqPackageAccess", "private package must be linked to a repository to be accessed by Actions") + return + } + + // 2. Check Org Cross-Repo Access Policy if ctx.Package.Owner.IsOrganization() { cfg, err := actions_model.GetOrgActionsConfig(ctx, ctx.Package.Owner.ID) if err != nil { @@ -116,16 +121,11 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.Context) { ctx.HTTPError(http.StatusForbidden, "reqPackageAccess", "cross-repository package access is disabled") return } - } else { - // For user-owned packages, maybe stricter? Or same? - // Issue says "only when they have been linked". - // If Owner is User, Cross-Repo setting is not available (it's Org setting). - // Default to Strict for Users? - if task.RepoID != ctx.Package.RepoID { - ctx.HTTPError(http.StatusForbidden, "reqPackageAccess", "package must be linked to the repository") - return - } } + + // 3. Fallthrough to GetActionsUserRepoPermission + // We rely on the backend permission check below to handle other Cross-Repository restrictions + // (e.g., User collaborative owners, token scopes). } } } diff --git a/routers/web/org/setting/actions.go b/routers/web/org/setting/actions.go index 1b35681889..fba4e2905c 100644 --- a/routers/web/org/setting/actions.go +++ b/routers/web/org/setting/actions.go @@ -9,12 +9,12 @@ import ( 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/modules/templates" "code.gitea.io/gitea/services/context" ) const ( - tplSettingsActionsGeneral base.TplName = "org/settings/actions_general" + tplSettingsActionsGeneral templates.TplName = "org/settings/actions_general" ) // ActionsGeneral renders the actions general settings page @@ -24,7 +24,7 @@ func ActionsGeneral(ctx *context.Context) { ctx.Data["PageIsOrgSettingsActions"] = true // Load Org Actions Config - actionsCfg, err := actions_model.GetOrgActionsConfig(ctx, ctx.Org.Organization.ID) + actionsCfg, err := actions_model.GetOrgActionsConfig(ctx, ctx.Org.Organization.AsUser().ID) if err != nil { ctx.ServerError("GetOrgActionsConfig", err) return @@ -35,6 +35,7 @@ func ActionsGeneral(ctx *context.Context) { ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted ctx.Data["TokenPermissionModeCustom"] = repo_model.ActionsTokenPermissionModeCustom ctx.Data["DefaultTokenPermissions"] = actionsCfg.GetEffectiveTokenPermissions(false) + ctx.Data["MaxTokenPermissions"] = actionsCfg.GetMaxTokenPermissions() ctx.Data["AllowCrossRepoAccess"] = actionsCfg.AllowCrossRepoAccess @@ -47,7 +48,7 @@ func ActionsGeneralPost(ctx *context.Context) { ctx.Data["PageIsOrgSettings"] = true ctx.Data["PageIsOrgSettingsActions"] = true - actionsCfg, err := actions_model.GetOrgActionsConfig(ctx, ctx.Org.Organization.ID) + actionsCfg, err := actions_model.GetOrgActionsConfig(ctx, ctx.Org.Organization.AsUser().ID) if err != nil { ctx.ServerError("GetOrgActionsConfig", err) return @@ -84,10 +85,30 @@ func ActionsGeneralPost(ctx *context.Context) { actionsCfg.DefaultTokenPermissions = nil } + // Update Maximum Permissions + parseMaxPerm := func(name string) perm.AccessMode { + if ctx.FormBool("max_" + name + "_write") { + return perm.AccessModeWrite + } + if ctx.FormBool("max_" + name + "_read") { + return perm.AccessModeRead + } + return perm.AccessModeNone + } + + actionsCfg.MaxTokenPermissions = &repo_model.ActionsTokenPermissions{ + Actions: parseMaxPerm("actions"), + Contents: parseMaxPerm("contents"), + Issues: parseMaxPerm("issues"), + Packages: parseMaxPerm("packages"), + PullRequests: parseMaxPerm("pull_requests"), + Wiki: parseMaxPerm("wiki"), + } + // Update Cross-Repo Access actionsCfg.AllowCrossRepoAccess = ctx.FormBool("allow_cross_repo_access") - if err := actions_model.SetOrgActionsConfig(ctx, ctx.Org.Organization.ID, actionsCfg); err != nil { + if err := actions_model.SetOrgActionsConfig(ctx, ctx.Org.Organization.AsUser().ID, actionsCfg); err != nil { ctx.ServerError("SetOrgActionsConfig", err) return } diff --git a/routers/web/repo/setting/actions.go b/routers/web/repo/setting/actions.go index 79875a00eb..673af0a0bd 100644 --- a/routers/web/repo/setting/actions.go +++ b/routers/web/repo/setting/actions.go @@ -43,6 +43,7 @@ func ActionsGeneralSettings(ctx *context.Context) { ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted ctx.Data["TokenPermissionModeCustom"] = repo_model.ActionsTokenPermissionModeCustom ctx.Data["DefaultTokenPermissions"] = actionsCfg.GetEffectiveTokenPermissions(false) + ctx.Data["MaxTokenPermissions"] = actionsCfg.GetMaxTokenPermissions() if ctx.Repo.Repository.IsPrivate { collaborativeOwnerIDs := actionsCfg.CollaborativeOwnerIDs @@ -177,6 +178,26 @@ func UpdateTokenPermissions(ctx *context.Context) { actionsCfg.DefaultTokenPermissions = nil } + // Update Maximum Permissions + parseMaxPerm := func(name string) perm.AccessMode { + if ctx.FormBool("max_" + name + "_write") { + return perm.AccessModeWrite + } + if ctx.FormBool("max_" + name + "_read") { + return perm.AccessModeRead + } + return perm.AccessModeNone + } + + actionsCfg.MaxTokenPermissions = &repo_model.ActionsTokenPermissions{ + Actions: parseMaxPerm("actions"), + Contents: parseMaxPerm("contents"), + Issues: parseMaxPerm("issues"), + Packages: parseMaxPerm("packages"), + PullRequests: parseMaxPerm("pull_requests"), + Wiki: parseMaxPerm("wiki"), + } + 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 b66c8121e2..dbae8a1cbb 100644 --- a/templates/org/settings/actions_general.tmpl +++ b/templates/org/settings/actions_general.tmpl @@ -139,6 +139,96 @@ +
+
{{ctx.Locale.Tr "general.token_permissions.maximum"}}
+

{{ctx.Locale.Tr "general.token_permissions.maximum.description"}}

+
+ +
+
+ +
+ + +
+
+ + +
+
+
+ +
+
+ +
+ + +
+
+ + +
+
+
+ +
+
+ +
+ + +
+
+ + +
+
+
+ +
+
+ +
+ + +
+
+ + +
+
+
+ +
+
+ +
+ + +
+
+ + +
+
+
+ +
+
+ +
+ + +
+
+ + +
+
+
+
+ {{template "org/settings/layout_footer" .}} diff --git a/templates/repo/settings/actions_general.tmpl b/templates/repo/settings/actions_general.tmpl index 6326ab0a87..8b2374fa2d 100644 --- a/templates/repo/settings/actions_general.tmpl +++ b/templates/repo/settings/actions_general.tmpl @@ -195,6 +195,96 @@ +
+
{{ctx.Locale.Tr "general.token_permissions.maximum"}}
+

{{ctx.Locale.Tr "general.token_permissions.maximum.description"}}

+
+ +
+
+ +
+ + +
+
+ + +
+
+
+ +
+
+ +
+ + +
+
+ + +
+
+
+ +
+
+ +
+ + +
+
+ + +
+
+
+ +
+
+ +
+ + +
+
+ + +
+
+
+ +
+
+ +
+ + +
+
+ + +
+
+
+ +
+
+ +
+ + +
+
+ + +
+
+
+
+

{{ctx.Locale.Tr "actions.general.token_permissions.fork_pr_note"}}