mirror of
https://github.com/go-gitea/gitea.git
synced 2026-01-20 15:44:54 +01:00
fixes
This commit is contained in:
parent
feb791cccf
commit
7cccb84fdb
@ -346,13 +346,37 @@ func GetActionsUserRepoPermission(ctx context.Context, repo *repo_model.Reposito
|
||||
effectivePerms, err = repo_model.UnmarshalTokenPermissions(task.Job.TokenPermissions)
|
||||
if err != nil {
|
||||
// Fall back to repository settings if unmarshal fails
|
||||
effectivePerms = actionsCfg.GetEffectiveTokenPermissions(task.IsForkPullRequest)
|
||||
effectivePerms = actionsCfg.ClampPermissions(effectivePerms)
|
||||
// If following org config, we need to load it
|
||||
if !actionsCfg.OverrideOrgConfig && repo.Owner.IsOrganization() {
|
||||
orgCfg, err := actions_model.GetOrgActionsConfig(ctx, repo.OwnerID)
|
||||
if err != nil {
|
||||
log.Error("GetOrgActionsConfig: %v", err)
|
||||
effectivePerms = actionsCfg.GetEffectiveTokenPermissions(task.IsForkPullRequest) // Fallback to repo config on error
|
||||
} else {
|
||||
effectivePerms = orgCfg.GetEffectiveTokenPermissions(task.IsForkPullRequest)
|
||||
effectivePerms = orgCfg.ClampPermissions(effectivePerms)
|
||||
}
|
||||
} else {
|
||||
effectivePerms = actionsCfg.GetEffectiveTokenPermissions(task.IsForkPullRequest)
|
||||
effectivePerms = actionsCfg.ClampPermissions(effectivePerms)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No workflow permissions or job not found, use repository settings
|
||||
effectivePerms = actionsCfg.GetEffectiveTokenPermissions(task.IsForkPullRequest)
|
||||
effectivePerms = actionsCfg.ClampPermissions(effectivePerms)
|
||||
if !actionsCfg.OverrideOrgConfig && repo.Owner.IsOrganization() {
|
||||
orgCfg, err := actions_model.GetOrgActionsConfig(ctx, repo.OwnerID)
|
||||
if err != nil {
|
||||
log.Error("GetOrgActionsConfig: %v", err)
|
||||
effectivePerms = actionsCfg.GetEffectiveTokenPermissions(task.IsForkPullRequest) // Fallback to repo config on error
|
||||
effectivePerms = actionsCfg.ClampPermissions(effectivePerms)
|
||||
} else {
|
||||
effectivePerms = orgCfg.GetEffectiveTokenPermissions(task.IsForkPullRequest)
|
||||
effectivePerms = orgCfg.ClampPermissions(effectivePerms)
|
||||
}
|
||||
} else {
|
||||
effectivePerms = actionsCfg.GetEffectiveTokenPermissions(task.IsForkPullRequest)
|
||||
effectivePerms = actionsCfg.ClampPermissions(effectivePerms)
|
||||
}
|
||||
}
|
||||
|
||||
// Set up per-unit access modes based on configured permissions
|
||||
|
||||
@ -310,8 +310,8 @@ type ActionsConfig struct {
|
||||
AllowCrossRepoAccess bool `json:"allow_cross_repo_access,omitempty"`
|
||||
// AllowedCrossRepoIDs is a list of specific repo IDs that can be accessed cross-repo (empty means all if AllowCrossRepoAccess is true)
|
||||
AllowedCrossRepoIDs []int64 `json:"allowed_cross_repo_ids,omitempty"`
|
||||
// FollowOrgConfig indicates if this repository should follow the organization-level configuration
|
||||
FollowOrgConfig bool `json:"follow_org_config,omitempty"`
|
||||
// OverrideOrgConfig indicates if this repository should override the organization-level configuration
|
||||
OverrideOrgConfig bool `json:"override_org_config,omitempty"`
|
||||
}
|
||||
|
||||
func (cfg *ActionsConfig) EnableWorkflow(file string) {
|
||||
|
||||
@ -46,7 +46,7 @@ func ActionsGeneralSettings(ctx *context.Context) {
|
||||
|
||||
// Follow org config (only for repos in orgs)
|
||||
ctx.Data["IsInOrg"] = ctx.Repo.Repository.Owner.IsOrganization()
|
||||
ctx.Data["FollowOrgConfig"] = actionsCfg.FollowOrgConfig
|
||||
ctx.Data["OverrideOrgConfig"] = actionsCfg.OverrideOrgConfig
|
||||
|
||||
if ctx.Repo.Repository.IsPrivate {
|
||||
collaborativeOwnerIDs := actionsCfg.CollaborativeOwnerIDs
|
||||
@ -146,11 +146,12 @@ func UpdateTokenPermissions(ctx *context.Context) {
|
||||
|
||||
actionsCfg := actionsUnit.ActionsConfig()
|
||||
|
||||
// Update Follow Org Config (for repos in orgs)
|
||||
actionsCfg.FollowOrgConfig = ctx.FormBool("follow_org_config")
|
||||
// Update Override Org Config (for repos in orgs)
|
||||
// If checked, it means we WANT to override (opt-out of following)
|
||||
actionsCfg.OverrideOrgConfig = ctx.FormBool("override_org_config")
|
||||
|
||||
// Update permission mode (only if not following org config)
|
||||
if !actionsCfg.FollowOrgConfig {
|
||||
// Update permission mode (only if overriding org config)
|
||||
if actionsCfg.OverrideOrgConfig {
|
||||
permissionMode := repo_model.ActionsTokenPermissionMode(ctx.FormString("token_permission_mode"))
|
||||
if permissionMode == repo_model.ActionsTokenPermissionModeRestricted ||
|
||||
permissionMode == repo_model.ActionsTokenPermissionModePermissive ||
|
||||
@ -164,7 +165,7 @@ func UpdateTokenPermissions(ctx *context.Context) {
|
||||
}
|
||||
|
||||
// Update Maximum Permissions (radio buttons: none/read/write)
|
||||
if actionsCfg.TokenPermissionMode == repo_model.ActionsTokenPermissionModeCustom {
|
||||
if actionsCfg.OverrideOrgConfig && actionsCfg.TokenPermissionMode == repo_model.ActionsTokenPermissionModeCustom {
|
||||
parseMaxPerm := func(name string) perm.AccessMode {
|
||||
value := ctx.FormString("max_" + name)
|
||||
switch value {
|
||||
|
||||
@ -33,13 +33,13 @@
|
||||
{{.CsrfTokenHtml}}
|
||||
|
||||
{{if .IsInOrg}}
|
||||
<!-- Follow Organization Configuration -->
|
||||
<!-- Override Organization Configuration -->
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="follow_org_config" id="follow-org-config" {{if .FollowOrgConfig}}checked{{end}} class="js-follow-org-config">
|
||||
<label><strong>{{ctx.Locale.Tr "actions.general.token_permissions.follow_org"}}</strong></label>
|
||||
<input type="checkbox" name="override_org_config" id="override-org-config" {{if .OverrideOrgConfig}}checked{{end}} class="js-follow-org-config">
|
||||
<label><strong>{{ctx.Locale.Tr "actions.general.token_permissions.override_org"}}</strong></label>
|
||||
</div>
|
||||
<p class="help">{{ctx.Locale.Tr "actions.general.token_permissions.follow_org_desc"}}</p>
|
||||
<p class="help">{{ctx.Locale.Tr "actions.general.token_permissions.override_org_desc"}}</p>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
@ -177,7 +177,7 @@ func testActionsTokenPermissionsMode(u *url.URL, mode string, expectReadOnly boo
|
||||
require.NoError(t, err, "Actions unit should exist for repo4")
|
||||
actionsCfg := actionsUnit.ActionsConfig()
|
||||
actionsCfg.TokenPermissionMode = repo_model.ActionsTokenPermissionMode(mode)
|
||||
actionsCfg.MaxTokenPermissions = nil // Ensure no max permissions interfere
|
||||
actionsCfg.MaxTokenPermissions = nil // Ensure no max permissions interfere
|
||||
// Update the config
|
||||
actionsUnit.Config = actionsCfg
|
||||
require.NoError(t, repo_model.UpdateRepoUnit(t.Context(), actionsUnit))
|
||||
@ -343,11 +343,12 @@ func TestActionsTokenPackagePermission(t *testing.T) {
|
||||
runner := newMockRunner()
|
||||
runner.registerAsRepoRunner(t, repo.OwnerName, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false)
|
||||
|
||||
// Set Config: Custom Mode, Max Packages = Write
|
||||
// This should implied Default Packages = Write (because Custom defaults to Max)
|
||||
// Set Config: Custom Mode, Max Packages = Write, Max Code = Read
|
||||
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/settings/actions/general/token_permissions", repo.OwnerName, repo.Name), map[string]string{
|
||||
"override_org_config": "true",
|
||||
"token_permission_mode": "custom",
|
||||
"max_packages": "write",
|
||||
"max_code": "read", // Ensure repo read access if needed
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
@ -375,7 +376,7 @@ jobs:
|
||||
writePackageURL := fmt.Sprintf("/api/packages/%s/generic/%s/%s/test.bin", user2.Name, packageName, packageVersion)
|
||||
uploadReq := NewRequestWithBody(t, "PUT", writePackageURL, bytes.NewReader([]byte{1, 2, 3})).
|
||||
AddTokenAuth(taskToken)
|
||||
|
||||
|
||||
// Should Succeed (201)
|
||||
MakeRequest(t, uploadReq, http.StatusCreated)
|
||||
})
|
||||
@ -441,26 +442,26 @@ func TestActionsCrossRepoAccess(t *testing.T) {
|
||||
Reponame: "repo-B",
|
||||
}
|
||||
|
||||
// Case A: Default (AllowCrossRepoAccess = false/unset) -> Should Fail (404 Not Found)
|
||||
// API returns 404 for private repos you can't access, not 403, to avoid leaking existence.
|
||||
testCtx.ExpectedCode = http.StatusNotFound
|
||||
t.Run("Cross-Repo Access Denied (Default)", doAPIGetRepository(testCtx, nil))
|
||||
// Case A: Default (AllowCrossRepoAccess = true by default now) -> Should Succeed (200) Read-Only
|
||||
// API returns 404 if denied (hidden), 200 if allowed.
|
||||
testCtx.ExpectedCode = http.StatusOK
|
||||
t.Run("Cross-Repo Access Allowed (Default)", doAPIGetRepository(testCtx, func(t *testing.T, r structs.Repository) {
|
||||
assert.Equal(t, "repo-B", r.Name)
|
||||
}))
|
||||
|
||||
// Case B: Enable AllowCrossRepoAccess
|
||||
// Case B: Explicitly Disable AllowCrossRepoAccess
|
||||
org, err := org_model.GetOrgByName(t.Context(), orgName)
|
||||
require.NoError(t, err)
|
||||
|
||||
cfg := &repo_model.ActionsConfig{
|
||||
AllowCrossRepoAccess: true,
|
||||
AllowCrossRepoAccess: false,
|
||||
}
|
||||
err = actions_model.SetOrgActionsConfig(t.Context(), org.ID, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Retry -> Should Succeed (200) - Read Only
|
||||
testCtx.ExpectedCode = http.StatusOK
|
||||
t.Run("Cross-Repo Access Allowed", doAPIGetRepository(testCtx, func(t *testing.T, r structs.Repository) {
|
||||
assert.Equal(t, "repo-B", r.Name)
|
||||
}))
|
||||
// Retry -> Should Fail (404 Not Found)
|
||||
testCtx.ExpectedCode = http.StatusNotFound
|
||||
t.Run("Cross-Repo Access Denied (Disabled)", doAPIGetRepository(testCtx, nil))
|
||||
|
||||
// 6. Test Cross-Repo Package Access
|
||||
t.Run("Cross-Repo Package Access", func(t *testing.T) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user