Skip to content

Commit

Permalink
Merge pull request #6876 from getkirby/v5/feature/access-permissions-2
Browse files Browse the repository at this point in the history
Access permissions 2: New `LanguagePermissions` class
  • Loading branch information
bastianallgeier authored Dec 20, 2024
2 parents 8b1b969 + 2be7d6d commit 3ca5f87
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 22 deletions.
8 changes: 8 additions & 0 deletions src/Cms/Language.php
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,14 @@ public function pattern(): string
return $path . '/(:all?)';
}

/**
* Returns the permissions object for this language
*/
public function permissions(): LanguagePermissions
{
return new LanguagePermissions($this);
}

/**
* Returns the absolute path to the language file
*/
Expand Down
22 changes: 22 additions & 0 deletions src/Cms/LanguagePermissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Kirby\Cms;

/**
* LanguagePermissions
*
* @package Kirby Cms
* @author Ahmet Bora <[email protected]>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://getkirby.com/license
*/
class LanguagePermissions extends ModelPermissions
{
protected string $category = 'languages';

protected function canDelete(): bool
{
return $this->model->isDeletable() === true;
}
}
18 changes: 3 additions & 15 deletions src/Cms/LanguageRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ public static function create(Language $language): void
);
}

$user = App::instance()->user();

if ($user?->role()->permissions()->for('languages', 'create') !== true) {
if ($language->permissions()->create() !== true) {
throw new PermissionException(
key: 'language.create.permission'
);
Expand All @@ -54,15 +52,7 @@ public static function create(Language $language): void
*/
public static function delete(Language $language): void
{
if ($language->isDeletable() === false) {
throw new LogicException(
message: 'The language cannot be deleted'
);
}

$user = App::instance()->user();

if ($user?->role()->permissions()->for('languages', 'delete') !== true) {
if ($language->permissions()->delete() !== true) {
throw new PermissionException(
key: 'language.delete.permission'
);
Expand Down Expand Up @@ -93,9 +83,7 @@ public static function update(
);
}

$user = $kirby->user();

if ($user?->role()->permissions()->for('languages', 'update') !== true) {
if ($newLanguage->permissions()->update() !== true) {
throw new PermissionException(
key: 'language.update.permission'
);
Expand Down
10 changes: 7 additions & 3 deletions src/Cms/ModelPermissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,21 @@
abstract class ModelPermissions
{
protected string $category;
protected ModelWithContent $model;
protected ModelWithContent|Language $model;
protected array $options;
protected Permissions $permissions;
protected User $user;

public function __construct(ModelWithContent $model)
public function __construct(ModelWithContent|Language $model)
{
$this->model = $model;
$this->options = $model->blueprint()->options();
$this->user = $model->kirby()->user() ?? User::nobody();
$this->permissions = $this->user->role()->permissions();

$this->options = match (true) {
$model instanceof ModelWithContent => $model->blueprint()->options(),
default => []
};
}

public function __call(string $method, array $arguments = []): bool
Expand Down
145 changes: 145 additions & 0 deletions tests/Cms/Languages/LanguagePermissionsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php

namespace Kirby\Cms;

use Kirby\TestCase;

/**
* @coversDefaultClass \Kirby\Cms\LanguagePermissions
*/
class LanguagePermissionsTest extends TestCase
{
public static function actionProvider(): array
{
return [
['create'],
['delete'],
['update'],
];
}

/**
* @covers \Kirby\Cms\ModelPermissions::can
* @dataProvider actionProvider
*/
public function testWithAdmin($action)
{
$kirby = new App([
'roots' => [
'index' => '/dev/null'
],
'roles' => [
['name' => 'admin'],
['name' => 'editor']
]
]);

$kirby->impersonate('kirby');

$language = new Language(['code' => 'en']);
$perms = $language->permissions();

$this->assertTrue($perms->can($action));
}

/**
* @covers \Kirby\Cms\ModelPermissions::can
* @dataProvider actionProvider
*/
public function testWithNobody($action)
{
new App([
'roots' => [
'index' => '/dev/null'
],
'roles' => [
['name' => 'admin'],
['name' => 'editor']
]
]);

$language = new Language(['code' => 'en']);
$perms = $language->permissions();

$this->assertFalse($perms->can($action));
}

/**
* @covers \Kirby\Cms\ModelPermissions::can
* @dataProvider actionProvider
*/
public function testWithNoAdmin($action)
{
$app = new App([
'languages' => [
[
'code' => 'en'
]
],
'roots' => [
'index' => '/dev/null'
],
'roles' => [
['name' => 'admin'],
[
'name' => 'editor',
'permissions' => [
'languages' => [
'create' => false,
'delete' => false,
'update' => false
],
]
]
],
'user' => '[email protected]',
'users' => [
[
'email' => '[email protected]',
'role' => 'admin'
],
[
'email' => '[email protected]',
'role' => 'editor'
]
],
]);

$language = $app->language('en');
$perms = $language->permissions();

$this->assertSame('editor', $app->role()->name());
$this->assertFalse($perms->can($action));
}

/**
* @covers ::canDelete
*/
public function testCanDeleteWhenNotDeletable()
{
$app = new App([
'languages' => [
[
'code' => 'en',
'default' => true
],
[
'code' => 'de'
]
],
'roots' => [
'index' => '/dev/null'
],
'roles' => [
['name' => 'admin']
]
]);

$app->impersonate('kirby');

$language = $app->language('en');
$perms = $language->permissions();

$this->assertFalse($perms->can('delete'));
}
}
4 changes: 2 additions & 2 deletions tests/Cms/Languages/LanguageRulesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ public function testDeleteWhenNotDeletable()
$language = $this->createMock(Language::class);
$language->method('isDeletable')->willReturn(false);

$this->expectException(LogicException::class);
$this->expectExceptionMessage('The language cannot be deleted');
$this->expectException(PermissionException::class);
$this->expectExceptionMessage('You are not allowed to delete the language');

LanguageRules::delete($language);
}
Expand Down
12 changes: 10 additions & 2 deletions tests/Cms/Users/UserPermissionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,24 @@ public function testWithNoAdmin($action)

public function testChangeSingleRole()
{
new App([
$app = new App([
'roots' => [
'index' => '/dev/null'
],
'roles' => [
['name' => 'admin']
],
'users' => [
[
'email' => '[email protected]',
'role' => 'admin'
]
]
]);

$user = new User(['email' => '[email protected]']);
$app->impersonate('kirby');

$user = $app->user('[email protected]');
$perms = $user->permissions();

$this->assertFalse($perms->can('changeRole'));
Expand Down

0 comments on commit 3ca5f87

Please sign in to comment.