diff --git a/src/Cms/ModelPermissions.php b/src/Cms/ModelPermissions.php index a9e75cc0c0..e5baa290a9 100644 --- a/src/Cms/ModelPermissions.php +++ b/src/Cms/ModelPermissions.php @@ -17,14 +17,9 @@ abstract class ModelPermissions { protected string $category; protected array $options; - protected Permissions $permissions; - protected User $user; public function __construct(protected ModelWithContent|Language $model) { - $this->user = $model->kirby()->user() ?? User::nobody(); - $this->permissions = $this->user->role()->permissions(); - $this->options = match (true) { $model instanceof ModelWithContent => $model->blueprint()->options(), default => [] @@ -55,8 +50,9 @@ public function can( string $action, bool $default = false ): bool { - $user = $this->user->id(); - $role = $this->user->role()->id(); + $user = $this->user(); + $userId = $user->id(); + $role = $user->role()->id(); // users with the `nobody` role can do nothing // that needs a permission check @@ -75,7 +71,7 @@ public function can( } // the almighty `kirby` user can do anything - if ($user === 'kirby' && $role === 'admin') { + if ($userId === 'kirby' && $role === 'admin') { return true; } @@ -105,7 +101,8 @@ public function can( } } - return $this->permissions->for($this->category, $action, $default); + $permissions = $this->user()->role()->permissions(); + return $permissions->for($this->category(), $action, $default); } /** @@ -121,6 +118,15 @@ public function cannot( return $this->can($action, !$default) === false; } + /** + * Can be overridden by specific child classes + * if the permission category needs to be dynamic + */ + protected function category(): string + { + return $this->category; + } + public function toArray(): array { $array = []; @@ -131,4 +137,12 @@ public function toArray(): array return $array; } + + /** + * Returns the currently logged in user + */ + protected function user(): User + { + return $this->model->kirby()->user() ?? User::nobody(); + } } diff --git a/src/Cms/UserPermissions.php b/src/Cms/UserPermissions.php index cab3776551..6b9ca49cc9 100644 --- a/src/Cms/UserPermissions.php +++ b/src/Cms/UserPermissions.php @@ -13,23 +13,12 @@ */ class UserPermissions extends ModelPermissions { - protected string $category = 'users'; - - public function __construct(User $model) - { - parent::__construct($model); - - // change the scope of the permissions, - // when the current user is this user - $this->category = $this->user?->is($model) ? 'user' : 'users'; - } - protected function canChangeRole(): bool { // protect admin from role changes by non-admin if ( $this->model->isAdmin() === true && - $this->user->isAdmin() !== true + $this->user()->isAdmin() !== true ) { return false; } @@ -45,7 +34,7 @@ protected function canChangeRole(): bool protected function canCreate(): bool { // the admin can always create new users - if ($this->user->isAdmin() === true) { + if ($this->user()->isAdmin() === true) { return true; } @@ -61,4 +50,11 @@ protected function canDelete(): bool { return $this->model->isLastAdmin() !== true; } + + protected function category(): string + { + // change the scope of the permissions, + // when the current user is this user + return $this->user()->is($this->model) ? 'user' : 'users'; + } } diff --git a/tests/Cms/Users/UserPermissionsTest.php b/tests/Cms/Users/UserPermissionsTest.php index e8d72b20d5..0b4a06f058 100644 --- a/tests/Cms/Users/UserPermissionsTest.php +++ b/tests/Cms/Users/UserPermissionsTest.php @@ -74,7 +74,6 @@ public function testWithNoAdmin($action) 'index' => '/dev/null' ], 'roles' => [ - ['name' => 'admin'], [ 'name' => 'editor', 'permissions' => [ @@ -88,36 +87,41 @@ public function testWithNoAdmin($action) 'update' => false ], 'users' => [ - 'changeEmail' => false, - 'changeLanguage' => false, - 'changeName' => false, - 'changePassword' => false, - 'changeRole' => false, - 'create' => false, - 'delete' => false, - 'update' => false + 'changeEmail' => true, + 'changeLanguage' => true, + 'changeName' => true, + 'changePassword' => true, + 'changeRole' => true, + 'create' => true, + 'delete' => true, + 'update' => true ] ] ] ], - 'user' => 'editor@getkirby.com', + 'user' => 'editor1@getkirby.com', 'users' => [ [ - 'email' => 'admin@getkirby.com', - 'role' => 'admin' + 'email' => 'editor1@getkirby.com', + 'role' => 'editor' ], [ - 'email' => 'editor@getkirby.com', + 'email' => 'editor2@getkirby.com', 'role' => 'editor' ] ], ]); - $user = $app->user(); - $perms = $user->permissions(); + // `user` permissions are disabled + $user1 = $app->user(); + $perms1 = $user1->permissions(); + $this->assertSame('editor', $user1->role()->name()); + $this->assertFalse($perms1->can($action)); - $this->assertSame('editor', $user->role()->name()); - $this->assertFalse($perms->can($action)); + // `users` permissions are enabled + $user2 = $app->user('editor2@getkirby.com'); + $perms2 = $user2->permissions(); + $this->assertTrue($perms2->can($action)); } public function testChangeSingleRole()