diff --git a/routers/web/repo/setting/actions.go b/routers/web/repo/setting/actions.go index 724233a153..29e525665b 100644 --- a/routers/web/repo/setting/actions.go +++ b/routers/web/repo/setting/actions.go @@ -40,8 +40,6 @@ func ActionsGeneralSettings(ctx *context.Context) { ctx.Data["TokenPermissionMode"] = actionsCfg.GetTokenPermissionMode() ctx.Data["TokenPermissionModePermissive"] = repo_model.ActionsTokenPermissionModePermissive ctx.Data["TokenPermissionModeRestricted"] = repo_model.ActionsTokenPermissionModeRestricted - ctx.Data["EffectiveTokenPermissions"] = actionsCfg.GetEffectiveTokenPermissions(false) - ctx.Data["MaxTokenPermissions"] = actionsCfg.GetMaxTokenPermissions() if ctx.Repo.Repository.IsPrivate { collaborativeOwnerIDs := actionsCfg.CollaborativeOwnerIDs @@ -142,11 +140,13 @@ func UpdateTokenPermissions(ctx *context.Context) { actionsCfg := actionsUnit.ActionsConfig() // Update permission mode - permissionMode := ctx.FormString("token_permission_mode") - if permissionMode == string(repo_model.ActionsTokenPermissionModeRestricted) { - actionsCfg.TokenPermissionMode = repo_model.ActionsTokenPermissionModeRestricted + permissionMode := repo_model.ActionsTokenPermissionMode(ctx.FormString("token_permission_mode")) + if permissionMode == repo_model.ActionsTokenPermissionModeRestricted || permissionMode == repo_model.ActionsTokenPermissionModePermissive { + actionsCfg.TokenPermissionMode = permissionMode } else { - actionsCfg.TokenPermissionMode = repo_model.ActionsTokenPermissionModePermissive + ctx.Flash.Error("Invalid token permission mode") + ctx.Redirect(redirectURL) + return } if err := repo_model.UpdateRepoUnit(ctx, actionsUnit); err != nil { diff --git a/templates/repo/settings/actions_general.tmpl b/templates/repo/settings/actions_general.tmpl index 4a9d2512ba..3f2c429a4b 100644 --- a/templates/repo/settings/actions_general.tmpl +++ b/templates/repo/settings/actions_general.tmpl @@ -95,7 +95,7 @@ -
+

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

diff --git a/tests/integration/actions_job_token_test.go b/tests/integration/actions_job_token_test.go index f2559d618c..3b061895b3 100644 --- a/tests/integration/actions_job_token_test.go +++ b/tests/integration/actions_job_token_test.go @@ -154,8 +154,26 @@ func testActionsTokenPermissionsMode(u *url.URL, mode string, expectReadOnly boo require.Equal(t, "user5", r.Owner.UserName) })) - // For now, both modes allow write since the mode setting needs to be persisted to the repo unit - // This test validates the token permission infrastructure is working - // Once mode is applied to repository settings, the expectReadOnly parameter will control behavior + // Test Write Access + context.ExpectedCode = util.Iif(expectReadOnly, http.StatusForbidden, http.StatusCreated) + t.Run("API Create File", doAPICreateFile(context, "test-permissions.txt", &structs.CreateFileOptions{ + FileOptions: structs.FileOptions{ + NewBranchName: "new-branch-permissions", + Message: "Create File", + }, + ContentBase64: base64.StdEncoding.EncodeToString([]byte(`This is a test file for permissions.`)), + })) + + // Test Delete Access + context.ExpectedCode = util.Iif(expectReadOnly, http.StatusForbidden, http.StatusNoContent) + if !expectReadOnly { + // Clean up created file if we had write access + t.Run("API Delete File", doAPIDeleteFile(context, "test-permissions.txt", &structs.DeleteFileOptions{ + FileOptions: structs.FileOptions{ + BranchName: "new-branch-permissions", + Message: "Delete File", + }, + })) + } } } diff --git a/tests/integration/api_helper_for_declarative_test.go b/tests/integration/api_helper_for_declarative_test.go index b30cdfd0fc..d7dcad953c 100644 --- a/tests/integration/api_helper_for_declarative_test.go +++ b/tests/integration/api_helper_for_declarative_test.go @@ -374,6 +374,24 @@ func doAPICreateFile(ctx APITestContext, treepath string, options *api.CreateFil } } +func doAPIDeleteFile(ctx APITestContext, treepath string, options *api.DeleteFileOptions, callback ...func(*testing.T, api.FileDeleteResponse)) func(*testing.T) { + return func(t *testing.T) { + req := NewRequestWithJSON(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", ctx.Username, ctx.Reponame, treepath), &options). + AddTokenAuth(ctx.Token) + if ctx.ExpectedCode != 0 { + ctx.Session.MakeRequest(t, req, ctx.ExpectedCode) + return + } + resp := ctx.Session.MakeRequest(t, req, http.StatusOK) + + var contents api.FileDeleteResponse + DecodeJSON(t, resp, &contents) + if len(callback) > 0 { + callback[0](t, contents) + } + } +} + func doAPICreateOrganization(ctx APITestContext, options *api.CreateOrgOption, callback ...func(*testing.T, api.Organization)) func(t *testing.T) { return func(t *testing.T) { req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &options).