Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
44e2fb1
feat: New granular save and edit permissions
lukaskleinschmidt Jan 15, 2026
5c295e0
chore: Cleanup
lukaskleinschmidt Jan 22, 2026
d1e571f
Merge branch 'develop-minor' into feat/save-and-edit-permissions
lukaskleinschmidt Jan 22, 2026
b70d3ed
chore: Fix indentation
lukaskleinschmidt Jan 23, 2026
fa1acb0
fix: Improve error reporting
lukaskleinschmidt Jan 26, 2026
0b5d1a6
fix: Add canSave prop to FormControls
lukaskleinschmidt Jan 26, 2026
8ca20fb
fix: Fix button disabled state logic in FormControls
lukaskleinschmidt Jan 26, 2026
1b5a7c2
fix: Update permission checks to include edit capability
lukaskleinschmidt Jan 26, 2026
0c0b390
fix: Reduce normalization complexity
lukaskleinschmidt Feb 10, 2026
a67b0aa
fix: Update allowed defaults types
lukaskleinschmidt Feb 10, 2026
23e64fd
chore: Cleanup
lukaskleinschmidt Feb 12, 2026
395481c
refact: Remove try catch due to unintended problems in tests
lukaskleinschmidt Feb 12, 2026
275f8a3
refact: Add deprecation warning
lukaskleinschmidt Mar 2, 2026
b10acb0
fix: Fix API model tests
lukaskleinschmidt Mar 2, 2026
9ee6938
fix: Fix blueprint tests
lukaskleinschmidt Mar 2, 2026
90bfbbe
fix: Fix page blueprint test
lukaskleinschmidt Mar 2, 2026
0cb68af
fix: Fix rules tests
lukaskleinschmidt Mar 2, 2026
90a16b1
fix: Add extended actions to the defaults
lukaskleinschmidt Mar 2, 2026
cdd2345
fix: Fix isFocusable check
lukaskleinschmidt Mar 2, 2026
ef8fde3
fix: Fix tests
lukaskleinschmidt Mar 2, 2026
363742c
chore: Add remaining deprecation docs
lukasbestle Mar 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions panel/src/components/Forms/FormControls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
:key="button.text"
class="k-form-controls-button"
v-bind="button"
:disabled="isProcessing"
:disabled="button.disabled || isProcessing"
variant="filled"
:size="size"
/>
Expand Down Expand Up @@ -54,11 +54,16 @@
<script>
export const props = {
props: {
canSave: Boolean,
editor: String,
hasDiff: Boolean,
isLocked: Boolean,
isProcessing: Boolean,
modified: [String, Date],
permissions: {
type: Object,
default: () => ({})
},
/**
* Preview URL for changes
*/
Expand Down Expand Up @@ -102,10 +107,11 @@ export default {
click: () => this.discard()
},
{
disabled: this.canSave === false,
theme: "notice",
text: this.$t("save"),
icon: this.isProcessing ? "loader" : "check",
click: () => this.$emit("submit")
click: () => this.$emit("submit"),
},
{
theme: "notice",
Expand Down
1 change: 1 addition & 0 deletions panel/src/components/Views/Files/FileView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<k-view-buttons :buttons="buttons">
<template #after>
<k-form-controls
:can-save="permissions.save"
:editor="editor"
:has-diff="hasDiff"
:is-locked="isLocked"
Expand Down
1 change: 1 addition & 0 deletions panel/src/components/Views/Pages/PageView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<k-view-buttons :buttons="buttons">
<template #after>
<k-form-controls
:can-save="permissions.save"
:editor="editor"
:has-diff="hasDiff"
:is-locked="isLocked"
Expand Down
1 change: 1 addition & 0 deletions panel/src/components/Views/Pages/SiteView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<k-view-buttons :buttons="buttons">
<template #after>
<k-form-controls
:can-save="permissions.save"
:editor="editor"
:has-diff="hasDiff"
:is-locked="isLocked"
Expand Down
1 change: 1 addition & 0 deletions panel/src/components/Views/Preview/PreviewBrowser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
</p>
<k-form-controls
v-else
:can-save="permissions.save"
:editor="editor"
:has-diff="hasDiff"
:is-locked="isLocked"
Expand Down
1 change: 1 addition & 0 deletions panel/src/components/Views/Preview/PreviewView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export default {
isLocked: this.isLocked,
modified: this.modified,
label: this.$t("version." + versionId),
permissions: this.permissions,
src: this.src[versionId],
versionId: versionId
};
Expand Down
1 change: 1 addition & 0 deletions panel/src/components/Views/Users/UserView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<k-view-buttons :buttons="buttons">
<template #after>
<k-form-controls
:can-save="permissions.save"
:editor="editor"
:has-diff="hasDiff"
:is-locked="isLocked"
Expand Down
6 changes: 3 additions & 3 deletions src/Api/Controller/Changes.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ protected static function cleanup(ModelWithContent $model): void
*/
public static function discard(ModelWithContent $model): array
{
if ($model->permissions()->can('update') === false) {
if ($model->permissions()->can('edit') === false) {
throw new PermissionException(
key: 'version.discard.permission',
);
Expand All @@ -63,7 +63,7 @@ public static function discard(ModelWithContent $model): array
*/
public static function publish(ModelWithContent $model, array $input): array
{
if ($model->permissions()->can('update') === false) {
if ($model->permissions()->can('save') === false) {
throw new PermissionException(
key: 'version.publish.permission',
);
Expand Down Expand Up @@ -104,7 +104,7 @@ public static function publish(ModelWithContent $model, array $input): array
*/
public static function save(ModelWithContent $model, array $input): array
{
if ($model->permissions()->can('update') === false) {
if ($model->permissions()->can('edit') === false) {
throw new PermissionException(
key: 'version.save.permission',
);
Expand Down
15 changes: 13 additions & 2 deletions src/Cms/Blueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ protected function normalizeOptions(

// set all options to false
if ($options === false) {
return array_map(fn () => false, $defaults);
return array_fill_keys(array_keys($defaults), false);
}

// extend options if possible
Expand All @@ -684,7 +684,18 @@ protected function normalizeOptions(
$alias = $aliases[$key] ?? null;

if ($alias !== null) {
$options[$alias] ??= $value;
if (is_callable($alias) === true) {
$alias = $alias($value);
}

if (is_array($alias) === false) {
$alias = [$alias => $value];
}

foreach ($alias as $option => $value) {
$options[$option] ??= $value;
}

unset($options[$key]);
}
}
Expand Down
14 changes: 10 additions & 4 deletions src/Cms/FileBlueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,25 @@ public function __construct(array $props)

// normalize all available page options
$this->props['options'] = $this->normalizeOptions(
$this->props['options'] ?? true,
// defaults
[
options: $this->props['options'] ?? true,
defaults: [
'access' => null,
'changeName' => null,
'changeTemplate' => null,
'create' => null,
'delete' => null,
'edit' => null,
'list' => null,
'read' => null,
'replace' => null,
'save' => null,
'sort' => null,
'update' => null,
],
aliases: [
'update' => static fn ($value) => [
'edit' => $value,
'save' => $value,
],
]
);

Expand Down
5 changes: 4 additions & 1 deletion src/Cms/FileRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,10 @@ public static function replace(File $file, BaseFile $upload): void
*/
public static function update(File $file, array $content = []): void
{
if ($file->permissions()->can('update') !== true) {
if (
$file->permissions()->can('save') !== true ||
$file->permissions()->can('edit') !== true
) {
throw new PermissionException(
message: 'The file cannot be updated'
);
Expand Down
3 changes: 3 additions & 0 deletions src/Cms/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class Helpers
// The internal `$model->contentFile*()` methods have been deprecated
'model-content-file' => true,

// Passing `$category = null` to `Permissions::for()` is not supported
'permissions-for-category-null' => true,

// Passing an `info` array inside the `extends` array
// has been deprecated. Pass the individual entries (e.g. root, version)
// directly as named arguments.
Expand Down
15 changes: 9 additions & 6 deletions src/Cms/PageBlueprint.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ public function __construct(array $props)

// normalize all available page options
$this->props['options'] = $this->normalizeOptions(
$this->props['options'] ?? true,
// defaults
[
options: $this->props['options'] ?? true,
defaults: [
'access' => null,
'changeSlug' => null,
'changeStatus' => null,
Expand All @@ -34,19 +33,23 @@ public function __construct(array $props)
'create' => null,
'delete' => null,
'duplicate' => null,
'edit' => null,
'list' => null,
'move' => null,
'preview' => null,
'read' => null,
'save' => null,
'sort' => null,
'update' => null,
],
// aliases (from v2)
[
aliases: [
'status' => 'changeStatus',
'template' => 'changeTemplate',
'title' => 'changeTitle',
'url' => 'changeSlug',
'update' => static fn ($value) => [
'edit' => $value,
'save' => $value,
],
]
);

Expand Down
5 changes: 4 additions & 1 deletion src/Cms/PageRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,10 @@ public static function publish(Page $page): void
*/
public static function update(Page $page, array $content = []): void
{
if ($page->permissions()->can('update') !== true) {
if (
$page->permissions()->can('save') !== true ||
$page->permissions()->can('edit') !== true
) {
throw new PermissionException(
key: 'page.update.permission',
data: ['slug' => $page->slug()]
Expand Down
Loading