0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-05-12 02:33:50 +02:00

Final core implementation changes

This commit is contained in:
Excellencedev 2025-12-18 13:37:15 +01:00
parent 2a204e36a7
commit 297ecef8da
7 changed files with 241 additions and 16 deletions

View File

@ -313,6 +313,7 @@ func GetActionsUserRepoPermission(ctx context.Context, repo *repo_model.Reposito
// Get effective token permissions from repository settings // Get effective token permissions from repository settings
effectivePerms := actionsCfg.GetEffectiveTokenPermissions(task.IsForkPullRequest) effectivePerms := actionsCfg.GetEffectiveTokenPermissions(task.IsForkPullRequest)
effectivePerms = actionsCfg.ClampPermissions(effectivePerms)
// Set up per-unit access modes based on configured permissions // Set up per-unit access modes based on configured permissions
perm.units = repo.Units perm.units = repo.Units

View File

@ -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 = Custom permissions
general.token_permissions.custom.description = Configure permissions for each scope individually. general.token_permissions.custom.description = Configure permissions for each scope individually.
general.token_permissions.individual = Individual Permissions 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] [projects]
deleted.display_name = Deleted Project deleted.display_name = Deleted Project

View File

@ -103,8 +103,13 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.Context) {
} }
if task.RepoID != packageRepoID { if task.RepoID != packageRepoID {
// Not linked to the running repo. // 1. Private packages MUST be linked to a repository
// Check Org Policy 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() { if ctx.Package.Owner.IsOrganization() {
cfg, err := actions_model.GetOrgActionsConfig(ctx, ctx.Package.Owner.ID) cfg, err := actions_model.GetOrgActionsConfig(ctx, ctx.Package.Owner.ID)
if err != nil { 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") ctx.HTTPError(http.StatusForbidden, "reqPackageAccess", "cross-repository package access is disabled")
return 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).
} }
} }
} }

View File

@ -9,12 +9,12 @@ import (
actions_model "code.gitea.io/gitea/models/actions" actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/perm"
repo_model "code.gitea.io/gitea/models/repo" 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" "code.gitea.io/gitea/services/context"
) )
const ( const (
tplSettingsActionsGeneral base.TplName = "org/settings/actions_general" tplSettingsActionsGeneral templates.TplName = "org/settings/actions_general"
) )
// ActionsGeneral renders the actions general settings page // ActionsGeneral renders the actions general settings page
@ -24,7 +24,7 @@ func ActionsGeneral(ctx *context.Context) {
ctx.Data["PageIsOrgSettingsActions"] = true ctx.Data["PageIsOrgSettingsActions"] = true
// Load Org Actions Config // 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 { if err != nil {
ctx.ServerError("GetOrgActionsConfig", err) ctx.ServerError("GetOrgActionsConfig", err)
return return
@ -35,6 +35,7 @@ func ActionsGeneral(ctx *context.Context) {
ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted
ctx.Data["TokenPermissionModeCustom"] = repo_model.ActionsTokenPermissionModeCustom ctx.Data["TokenPermissionModeCustom"] = repo_model.ActionsTokenPermissionModeCustom
ctx.Data["DefaultTokenPermissions"] = actionsCfg.GetEffectiveTokenPermissions(false) ctx.Data["DefaultTokenPermissions"] = actionsCfg.GetEffectiveTokenPermissions(false)
ctx.Data["MaxTokenPermissions"] = actionsCfg.GetMaxTokenPermissions()
ctx.Data["AllowCrossRepoAccess"] = actionsCfg.AllowCrossRepoAccess ctx.Data["AllowCrossRepoAccess"] = actionsCfg.AllowCrossRepoAccess
@ -47,7 +48,7 @@ func ActionsGeneralPost(ctx *context.Context) {
ctx.Data["PageIsOrgSettings"] = true ctx.Data["PageIsOrgSettings"] = true
ctx.Data["PageIsOrgSettingsActions"] = 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 { if err != nil {
ctx.ServerError("GetOrgActionsConfig", err) ctx.ServerError("GetOrgActionsConfig", err)
return return
@ -84,10 +85,30 @@ func ActionsGeneralPost(ctx *context.Context) {
actionsCfg.DefaultTokenPermissions = nil 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 // Update Cross-Repo Access
actionsCfg.AllowCrossRepoAccess = ctx.FormBool("allow_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) ctx.ServerError("SetOrgActionsConfig", err)
return return
} }

View File

@ -43,6 +43,7 @@ func ActionsGeneralSettings(ctx *context.Context) {
ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted
ctx.Data["TokenPermissionModeCustom"] = repo_model.ActionsTokenPermissionModeCustom ctx.Data["TokenPermissionModeCustom"] = repo_model.ActionsTokenPermissionModeCustom
ctx.Data["DefaultTokenPermissions"] = actionsCfg.GetEffectiveTokenPermissions(false) ctx.Data["DefaultTokenPermissions"] = actionsCfg.GetEffectiveTokenPermissions(false)
ctx.Data["MaxTokenPermissions"] = actionsCfg.GetMaxTokenPermissions()
if ctx.Repo.Repository.IsPrivate { if ctx.Repo.Repository.IsPrivate {
collaborativeOwnerIDs := actionsCfg.CollaborativeOwnerIDs collaborativeOwnerIDs := actionsCfg.CollaborativeOwnerIDs
@ -177,6 +178,26 @@ func UpdateTokenPermissions(ctx *context.Context) {
actionsCfg.DefaultTokenPermissions = nil 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 { if err := repo_model.UpdateRepoUnit(ctx, actionsUnit); err != nil {
ctx.ServerError("UpdateRepoUnit", err) ctx.ServerError("UpdateRepoUnit", err)
return return

View File

@ -139,6 +139,96 @@
</form> </form>
</div> </div>
</div> </div>
<div class="divider"></div>
<h5 class="ui header">{{ctx.Locale.Tr "general.token_permissions.maximum"}}</h5>
<p class="tw-text-secondary">{{ctx.Locale.Tr "general.token_permissions.maximum.description"}}</p>
<div class="ui grid">
<!-- Actions -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "actions.actions"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_actions_read" {{if call $.MaxTokenPermissions.HasRead "actions"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_actions_write" {{if call $.MaxTokenPermissions.HasWrite "actions"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
<!-- Contents -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "general.token_permissions.contents"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_contents_read" {{if call $.MaxTokenPermissions.HasRead "contents"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_contents_write" {{if call $.MaxTokenPermissions.HasWrite "contents"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
<!-- Issues -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "general.token_permissions.issues"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_issues_read" {{if call $.MaxTokenPermissions.HasRead "issues"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_issues_write" {{if call $.MaxTokenPermissions.HasWrite "issues"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
<!-- Packages -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "general.token_permissions.packages"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_packages_read" {{if call $.MaxTokenPermissions.HasRead "packages"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_packages_write" {{if call $.MaxTokenPermissions.HasWrite "packages"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
<!-- Pull Requests -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "general.token_permissions.pull_requests"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_pull_requests_read" {{if call $.MaxTokenPermissions.HasRead "pull_requests"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_pull_requests_write" {{if call $.MaxTokenPermissions.HasWrite "pull_requests"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
<!-- Wiki -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "general.token_permissions.wiki"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_wiki_read" {{if call $.MaxTokenPermissions.HasRead "wiki"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_wiki_write" {{if call $.MaxTokenPermissions.HasWrite "wiki"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
{{template "org/settings/layout_footer" .}} {{template "org/settings/layout_footer" .}}

View File

@ -195,6 +195,96 @@
</div> </div>
</div> </div>
<div class="divider"></div>
<h5 class="ui header">{{ctx.Locale.Tr "general.token_permissions.maximum"}}</h5>
<p class="tw-text-secondary">{{ctx.Locale.Tr "general.token_permissions.maximum.description"}}</p>
<div class="ui grid">
<!-- Actions -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "actions.actions"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_actions_read" {{if call $.MaxTokenPermissions.HasRead "actions"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_actions_write" {{if call $.MaxTokenPermissions.HasWrite "actions"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
<!-- Contents -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "general.token_permissions.contents"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_contents_read" {{if call $.MaxTokenPermissions.HasRead "contents"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_contents_write" {{if call $.MaxTokenPermissions.HasWrite "contents"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
<!-- Issues -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "general.token_permissions.issues"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_issues_read" {{if call $.MaxTokenPermissions.HasRead "issues"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_issues_write" {{if call $.MaxTokenPermissions.HasWrite "issues"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
<!-- Packages -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "general.token_permissions.packages"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_packages_read" {{if call $.MaxTokenPermissions.HasRead "packages"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_packages_write" {{if call $.MaxTokenPermissions.HasWrite "packages"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
<!-- Pull Requests -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "general.token_permissions.pull_requests"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_pull_requests_read" {{if call $.MaxTokenPermissions.HasRead "pull_requests"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_pull_requests_write" {{if call $.MaxTokenPermissions.HasWrite "pull_requests"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
<!-- Wiki -->
<div class="eight wide column">
<div class="field">
<label>{{ctx.Locale.Tr "general.token_permissions.wiki"}}</label>
<div class="ui checkbox">
<input type="checkbox" name="max_wiki_read" {{if call $.MaxTokenPermissions.HasRead "wiki"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_read"}}</label>
</div>
<div class="ui checkbox">
<input type="checkbox" name="max_wiki_write" {{if call $.MaxTokenPermissions.HasWrite "wiki"}}checked{{end}}>
<label>{{ctx.Locale.Tr "general.token_permissions.access_write"}}</label>
</div>
</div>
</div>
</div>
<div class="ui info message"> <div class="ui info message">
<p>{{ctx.Locale.Tr "actions.general.token_permissions.fork_pr_note"}}</p> <p>{{ctx.Locale.Tr "actions.general.token_permissions.fork_pr_note"}}</p>
</div> </div>