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).