From c8716df284e74fad780ed8d36b23669d725b164a Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 8 Sep 2025 15:59:25 +0100 Subject: [PATCH 1/6] Permissions: Removed unused role-perm columns, added permission enum Updated main permission check methods to support our new enum. --- app/App/helpers.php | 3 +- app/Entities/Tools/PermissionsUpdater.php | 11 +- app/Permissions/Models/EntityPermission.php | 2 - app/Permissions/Models/RolePermission.php | 1 - app/Permissions/Permission.php | 151 ++++++++++++++++++ app/Permissions/PermissionApplicator.php | 16 +- app/Users/Models/Role.php | 3 +- app/Users/Models/User.php | 21 ++- ...25_09_02_111542_remove_unused_columns.php} | 5 + tests/Helpers/PermissionsProvider.php | 5 +- 10 files changed, 190 insertions(+), 28 deletions(-) create mode 100644 app/Permissions/Permission.php rename database/migrations/{2025_09_02_111542_remove_comments_text_column.php => 2025_09_02_111542_remove_unused_columns.php} (76%) diff --git a/app/App/helpers.php b/app/App/helpers.php index 2305c2d72..0e26d9974 100644 --- a/app/App/helpers.php +++ b/app/App/helpers.php @@ -3,6 +3,7 @@ use BookStack\App\AppVersion; use BookStack\App\Model; use BookStack\Facades\Theme; +use BookStack\Permissions\Permission; use BookStack\Permissions\PermissionApplicator; use BookStack\Settings\SettingService; use BookStack\Users\Models\User; @@ -39,7 +40,7 @@ function user(): User * Check if the current user has a permission. If an ownable element * is passed in the jointPermissions are checked against that particular item. */ -function userCan(string $permission, ?Model $ownable = null): bool +function userCan(string|Permission $permission, ?Model $ownable = null): bool { if (is_null($ownable)) { return user()->can($permission); diff --git a/app/Entities/Tools/PermissionsUpdater.php b/app/Entities/Tools/PermissionsUpdater.php index 9f3b8f952..4ca53982a 100644 --- a/app/Entities/Tools/PermissionsUpdater.php +++ b/app/Entities/Tools/PermissionsUpdater.php @@ -8,6 +8,7 @@ use BookStack\Entities\Models\Bookshelf; use BookStack\Entities\Models\Entity; use BookStack\Facades\Activity; use BookStack\Permissions\Models\EntityPermission; +use BookStack\Permissions\Permission; use BookStack\Users\Models\Role; use BookStack\Users\Models\User; use Illuminate\Http\Request; @@ -93,8 +94,9 @@ class PermissionsUpdater foreach ($permissions as $roleId => $info) { $entityPermissionData = ['role_id' => $roleId]; - foreach (EntityPermission::PERMISSIONS as $permission) { - $entityPermissionData[$permission] = (($info[$permission] ?? false) === "true"); + foreach (Permission::genericForEntity() as $permission) { + $permName = $permission->value; + $entityPermissionData[$permName] = (($info[$permName] ?? false) === "true"); } $formatted[] = $entityPermissionData; } @@ -108,8 +110,9 @@ class PermissionsUpdater foreach ($permissions as $requestPermissionData) { $entityPermissionData = ['role_id' => $requestPermissionData['role_id']]; - foreach (EntityPermission::PERMISSIONS as $permission) { - $entityPermissionData[$permission] = boolval($requestPermissionData[$permission] ?? false); + foreach (Permission::genericForEntity() as $permission) { + $permName = $permission->value; + $entityPermissionData[$permName] = boolval($requestPermissionData[$permName] ?? false); } $formatted[] = $entityPermissionData; } diff --git a/app/Permissions/Models/EntityPermission.php b/app/Permissions/Models/EntityPermission.php index 1ef9c2886..efad2ba39 100644 --- a/app/Permissions/Models/EntityPermission.php +++ b/app/Permissions/Models/EntityPermission.php @@ -18,8 +18,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; */ class EntityPermission extends Model { - public const PERMISSIONS = ['view', 'create', 'update', 'delete']; - protected $fillable = ['role_id', 'view', 'create', 'update', 'delete']; public $timestamps = false; protected $hidden = ['entity_id', 'entity_type', 'id']; diff --git a/app/Permissions/Models/RolePermission.php b/app/Permissions/Models/RolePermission.php index d43313ea0..67b1c55f5 100644 --- a/app/Permissions/Models/RolePermission.php +++ b/app/Permissions/Models/RolePermission.php @@ -9,7 +9,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; /** * @property int $id * @property string $name - * @property string $display_name */ class RolePermission extends Model { diff --git a/app/Permissions/Permission.php b/app/Permissions/Permission.php new file mode 100644 index 000000000..539bbe808 --- /dev/null +++ b/app/Permissions/Permission.php @@ -0,0 +1,151 @@ +value; + $explodedPermission = explode('-', $permissionName); $action = $explodedPermission[1] ?? $explodedPermission[0]; - $fullPermission = count($explodedPermission) > 1 ? $permission : $ownable->getMorphClass() . '-' . $permission; + $fullPermission = count($explodedPermission) > 1 ? $permissionName : $ownable->getMorphClass() . '-' . $permissionName; $user = $this->currentUser(); $userRoleIds = $this->getCurrentUserRoleIds(); @@ -235,8 +236,13 @@ class PermissionApplicator */ protected function ensureValidEntityAction(string $action): void { - if (!in_array($action, EntityPermission::PERMISSIONS)) { - throw new InvalidArgumentException('Action should be a simple entity permission action, not a role permission'); + $allowed = Permission::genericForEntity(); + foreach ($allowed as $permission) { + if ($permission->value === $action) { + return; + } } + + throw new InvalidArgumentException('Action should be a simple entity permission action, not a role permission'); } } diff --git a/app/Users/Models/Role.php b/app/Users/Models/Role.php index 912ae81c9..92be22458 100644 --- a/app/Users/Models/Role.php +++ b/app/Users/Models/Role.php @@ -57,7 +57,8 @@ class Role extends Model implements Loggable */ public function permissions(): BelongsToMany { - return $this->belongsToMany(RolePermission::class, 'permission_role', 'role_id', 'permission_id'); + return $this->belongsToMany(RolePermission::class, 'permission_role', 'role_id', 'permission_id') + ->select(['id', 'name']); } /** diff --git a/app/Users/Models/User.php b/app/Users/Models/User.php index f83e12088..0017653b5 100644 --- a/app/Users/Models/User.php +++ b/app/Users/Models/User.php @@ -12,6 +12,7 @@ use BookStack\Api\ApiToken; use BookStack\App\Model; use BookStack\App\SluggableInterface; use BookStack\Entities\Tools\SlugGenerator; +use BookStack\Permissions\Permission; use BookStack\Translation\LocaleDefinition; use BookStack\Translation\LocaleManager; use BookStack\Uploads\Image; @@ -26,7 +27,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Notifications\Notifiable; use Illuminate\Support\Collection; @@ -156,8 +156,9 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon /** * Check if the user has a particular permission. */ - public function can(string $permissionName): bool + public function can(string|Permission $permission): bool { + $permissionName = is_string($permission) ? $permission : $permission->value; return $this->permissions()->contains($permissionName); } @@ -181,9 +182,9 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon } /** - * Clear any cached permissions on this instance. + * Clear any cached permissions in this instance. */ - public function clearPermissionCache() + public function clearPermissionCache(): void { $this->permissions = null; } @@ -191,7 +192,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon /** * Attach a role to this user. */ - public function attachRole(Role $role) + public function attachRole(Role $role): void { $this->roles()->attach($role->id); $this->unsetRelation('roles'); @@ -207,15 +208,11 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon /** * Check if the user has a social account, - * If a driver is passed it checks for that single account type. - * - * @param bool|string $socialDriver - * - * @return bool + * If a driver is passed, it checks for that single account type. */ - public function hasSocialAccount($socialDriver = false) + public function hasSocialAccount(string $socialDriver = ''): bool { - if ($socialDriver === false) { + if (empty($socialDriver)) { return $this->socialAccounts()->count() > 0; } diff --git a/database/migrations/2025_09_02_111542_remove_comments_text_column.php b/database/migrations/2025_09_02_111542_remove_unused_columns.php similarity index 76% rename from database/migrations/2025_09_02_111542_remove_comments_text_column.php rename to database/migrations/2025_09_02_111542_remove_unused_columns.php index 8caa05e54..1ec2dfdf9 100644 --- a/database/migrations/2025_09_02_111542_remove_comments_text_column.php +++ b/database/migrations/2025_09_02_111542_remove_unused_columns.php @@ -14,6 +14,11 @@ return new class extends Migration Schema::table('comments', function (Blueprint $table) { $table->dropColumn('text'); }); + + Schema::table('role_permissions', function (Blueprint $table) { + $table->dropColumn('display_name'); + $table->dropColumn('description'); + }); } /** diff --git a/tests/Helpers/PermissionsProvider.php b/tests/Helpers/PermissionsProvider.php index cb036fe97..c9ae30919 100644 --- a/tests/Helpers/PermissionsProvider.php +++ b/tests/Helpers/PermissionsProvider.php @@ -5,6 +5,7 @@ namespace Tests\Helpers; use BookStack\Entities\Models\Entity; use BookStack\Permissions\Models\EntityPermission; use BookStack\Permissions\Models\RolePermission; +use BookStack\Permissions\Permission; use BookStack\Settings\SettingService; use BookStack\Users\Models\Role; use BookStack\Users\Models\User; @@ -139,8 +140,8 @@ class PermissionsProvider protected function actionListToEntityPermissionData(array $actionList, int $roleId = 0): array { $permissionData = ['role_id' => $roleId]; - foreach (EntityPermission::PERMISSIONS as $possibleAction) { - $permissionData[$possibleAction] = in_array($possibleAction, $actionList); + foreach (Permission::genericForEntity() as $permission) { + $permissionData[$permission->value] = in_array($permission->value, $actionList); } return $permissionData; From 5fc11d46d5115b96a2571fa371671c26900fab8f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 8 Sep 2025 16:15:42 +0100 Subject: [PATCH 2/6] Permissions: Added enum usage to controller helpers Also fixed various missing types or spelling/formatting points. Added down action for role_permission table changes in migration. --- app/Http/Controller.php | 27 +++++++++---------- app/Users/Controllers/RoleApiController.php | 13 ++++----- ...025_09_02_111542_remove_unused_columns.php | 5 ++++ 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/app/Http/Controller.php b/app/Http/Controller.php index 7f2134dd8..5d3be4951 100644 --- a/app/Http/Controller.php +++ b/app/Http/Controller.php @@ -6,6 +6,7 @@ use BookStack\Activity\Models\Loggable; use BookStack\App\Model; use BookStack\Exceptions\NotifyException; use BookStack\Facades\Activity; +use BookStack\Permissions\Permission; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Http\JsonResponse; @@ -27,10 +28,9 @@ abstract class Controller extends BaseController } /** - * Stops the application and shows a permission error if - * the application is in demo mode. + * Stops the application and shows a permission error if the application is in demo mode. */ - protected function preventAccessInDemoMode() + protected function preventAccessInDemoMode(): void { if (config('app.env') === 'demo') { $this->showPermissionError(); @@ -40,14 +40,13 @@ abstract class Controller extends BaseController /** * Adds the page title into the view. */ - public function setPageTitle(string $title) + public function setPageTitle(string $title): void { view()->share('pageTitle', $title); } /** - * On a permission error redirect to home and display. - * the error as a notification. + * On a permission error redirect to home and display the error as a notification. * * @throws NotifyException */ @@ -61,7 +60,7 @@ abstract class Controller extends BaseController /** * Checks that the current user has the given permission otherwise throw an exception. */ - protected function checkPermission(string $permission): void + protected function checkPermission(string|Permission $permission): void { if (!user() || !user()->can($permission)) { $this->showPermissionError(); @@ -81,7 +80,7 @@ abstract class Controller extends BaseController /** * Check the current user's permissions against an ownable item otherwise throw an exception. */ - protected function checkOwnablePermission(string $permission, Model $ownable, string $redirectLocation = '/'): void + protected function checkOwnablePermission(string|Permission $permission, Model $ownable, string $redirectLocation = '/'): void { if (!userCan($permission, $ownable)) { $this->showPermissionError($redirectLocation); @@ -92,7 +91,7 @@ abstract class Controller extends BaseController * Check if a user has a permission or bypass the permission * check if the given callback resolves true. */ - protected function checkPermissionOr(string $permission, callable $callback): void + protected function checkPermissionOr(string|Permission $permission, callable $callback): void { if ($callback() !== true) { $this->checkPermission($permission); @@ -103,7 +102,7 @@ abstract class Controller extends BaseController * Check if the current user has a permission or bypass if the provided user * id matches the current user. */ - protected function checkPermissionOrCurrentUser(string $permission, int $userId): void + protected function checkPermissionOrCurrentUser(string|Permission $permission, int $userId): void { $this->checkPermissionOr($permission, function () use ($userId) { return $userId === user()->id; @@ -111,7 +110,7 @@ abstract class Controller extends BaseController } /** - * Send back a json error message. + * Send back a JSON error message. */ protected function jsonError(string $messageText = '', int $statusCode = 500): JsonResponse { @@ -127,7 +126,7 @@ abstract class Controller extends BaseController } /** - * Show a positive, successful notification to the user on next view load. + * Show a positive, successful notification to the user on the next view load. */ protected function showSuccessNotification(string $message): void { @@ -135,7 +134,7 @@ abstract class Controller extends BaseController } /** - * Show a warning notification to the user on next view load. + * Show a warning notification to the user on the next view load. */ protected function showWarningNotification(string $message): void { @@ -143,7 +142,7 @@ abstract class Controller extends BaseController } /** - * Show an error notification to the user on next view load. + * Show an error notification to the user on the next view load. */ protected function showErrorNotification(string $message): void { diff --git a/app/Users/Controllers/RoleApiController.php b/app/Users/Controllers/RoleApiController.php index 2f3638cd3..6d87c9e27 100644 --- a/app/Users/Controllers/RoleApiController.php +++ b/app/Users/Controllers/RoleApiController.php @@ -10,8 +10,6 @@ use Illuminate\Support\Facades\DB; class RoleApiController extends ApiController { - protected PermissionsRepo $permissionsRepo; - protected array $fieldsToExpose = [ 'display_name', 'description', 'mfa_enforced', 'external_auth_id', 'created_at', 'updated_at', ]; @@ -35,10 +33,9 @@ class RoleApiController extends ApiController ] ]; - public function __construct(PermissionsRepo $permissionsRepo) - { - $this->permissionsRepo = $permissionsRepo; - + public function __construct( + protected PermissionsRepo $permissionsRepo + ) { // Checks for all endpoints in this controller $this->middleware(function ($request, $next) { $this->checkPermission('user-roles-manage'); @@ -125,9 +122,9 @@ class RoleApiController extends ApiController } /** - * Format the given role model for single-result display. + * Format the given role model for a single-result display. */ - protected function singleFormatter(Role $role) + protected function singleFormatter(Role $role): void { $role->load('users:id,name,slug'); $role->unsetRelation('permissions'); diff --git a/database/migrations/2025_09_02_111542_remove_unused_columns.php b/database/migrations/2025_09_02_111542_remove_unused_columns.php index 1ec2dfdf9..3a36e5ad6 100644 --- a/database/migrations/2025_09_02_111542_remove_unused_columns.php +++ b/database/migrations/2025_09_02_111542_remove_unused_columns.php @@ -29,5 +29,10 @@ return new class extends Migration Schema::table('comments', function (Blueprint $table) { $table->longText('text')->nullable(); }); + + Schema::table('role_permissions', function (Blueprint $table) { + $table->string('display_name')->nullable(); + $table->string('description')->nullable(); + }); } }; From 33a0237f875170e4750ea537604307dd9d5a0bde Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 8 Sep 2025 18:14:38 +0100 Subject: [PATCH 3/6] Permissions: Updated usage of controller methods to use enum --- app/Access/LoginService.php | 3 +- .../Controllers/AuditLogApiController.php | 5 +- .../Controllers/AuditLogController.php | 5 +- .../Controllers/CommentController.php | 17 ++--- app/Activity/Controllers/WatchController.php | 3 +- .../Handlers/BaseNotificationHandler.php | 3 +- app/Activity/Tools/UserEntityWatchOptions.php | 3 +- app/Api/ApiTokenGuard.php | 3 +- app/Api/UserApiTokenController.php | 13 ++-- app/App/helpers.php | 2 +- .../Controllers/BookApiController.php | 7 +- app/Entities/Controllers/BookController.php | 31 ++++----- .../Controllers/BookshelfApiController.php | 7 +- .../Controllers/BookshelfController.php | 15 +++-- .../Controllers/ChapterApiController.php | 9 +-- .../Controllers/ChapterController.php | 32 +++++---- .../Controllers/PageApiController.php | 9 +-- app/Entities/Controllers/PageController.php | 38 +++++------ .../Controllers/PageRevisionController.php | 5 +- .../Controllers/RecycleBinApiController.php | 5 +- .../Controllers/RecycleBinController.php | 5 +- app/Entities/Tools/PageContent.php | 3 +- app/Http/Middleware/ApiAuthenticate.php | 3 +- .../Middleware/CheckUserHasPermission.php | 7 +- .../ContentPermissionApiController.php | 4 +- app/Permissions/Permission.php | 66 +++++++------------ app/Permissions/PermissionsController.php | 20 +++--- app/Settings/MaintenanceController.php | 9 +-- app/Settings/SettingController.php | 5 +- app/Sorting/BookSortController.php | 5 +- .../Controllers/AttachmentApiController.php | 13 ++-- .../Controllers/AttachmentController.php | 32 ++++----- .../Controllers/DrawioImageController.php | 3 +- .../Controllers/GalleryImageController.php | 3 +- app/Uploads/Controllers/ImageController.php | 11 ++-- .../Controllers/ImageGalleryApiController.php | 11 ++-- app/Users/Controllers/RoleApiController.php | 3 +- app/Users/Controllers/RoleController.php | 15 +++-- .../Controllers/UserAccountController.php | 5 +- app/Users/Controllers/UserApiController.php | 4 +- app/Users/Controllers/UserController.php | 15 +++-- resources/views/home/books.blade.php | 2 +- resources/views/home/shelves.blade.php | 2 +- 43 files changed, 235 insertions(+), 226 deletions(-) diff --git a/app/Access/LoginService.php b/app/Access/LoginService.php index 76ae1938d..c81e95572 100644 --- a/app/Access/LoginService.php +++ b/app/Access/LoginService.php @@ -9,6 +9,7 @@ use BookStack\Exceptions\LoginAttemptInvalidUserException; use BookStack\Exceptions\StoppedAuthenticationException; use BookStack\Facades\Activity; use BookStack\Facades\Theme; +use BookStack\Permissions\Permission; use BookStack\Theming\ThemeEvents; use BookStack\Users\Models\User; use Exception; @@ -50,7 +51,7 @@ class LoginService Theme::dispatch(ThemeEvents::AUTH_LOGIN, $method, $user); // Authenticate on all session guards if a likely admin - if ($user->can('users-manage') && $user->can('user-roles-manage')) { + if ($user->can(Permission::UsersManage) && $user->can(Permission::UserRolesManage)) { $guards = ['standard', 'ldap', 'saml2', 'oidc']; foreach ($guards as $guard) { auth($guard)->login($user); diff --git a/app/Activity/Controllers/AuditLogApiController.php b/app/Activity/Controllers/AuditLogApiController.php index 650d17446..0cb4d9cb6 100644 --- a/app/Activity/Controllers/AuditLogApiController.php +++ b/app/Activity/Controllers/AuditLogApiController.php @@ -4,6 +4,7 @@ namespace BookStack\Activity\Controllers; use BookStack\Activity\Models\Activity; use BookStack\Http\ApiController; +use BookStack\Permissions\Permission; class AuditLogApiController extends ApiController { @@ -16,8 +17,8 @@ class AuditLogApiController extends ApiController */ public function list() { - $this->checkPermission('settings-manage'); - $this->checkPermission('users-manage'); + $this->checkPermission(Permission::SettingsManage); + $this->checkPermission(Permission::UsersManage); $query = Activity::query()->with(['user']); diff --git a/app/Activity/Controllers/AuditLogController.php b/app/Activity/Controllers/AuditLogController.php index 66ca30197..c4f9b91ed 100644 --- a/app/Activity/Controllers/AuditLogController.php +++ b/app/Activity/Controllers/AuditLogController.php @@ -5,6 +5,7 @@ namespace BookStack\Activity\Controllers; use BookStack\Activity\ActivityType; use BookStack\Activity\Models\Activity; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Sorting\SortUrl; use BookStack\Util\SimpleListOptions; use Illuminate\Http\Request; @@ -13,8 +14,8 @@ class AuditLogController extends Controller { public function index(Request $request) { - $this->checkPermission('settings-manage'); - $this->checkPermission('users-manage'); + $this->checkPermission(Permission::SettingsManage); + $this->checkPermission(Permission::UsersManage); $sort = $request->get('sort', 'activity_date'); $order = $request->get('order', 'desc'); diff --git a/app/Activity/Controllers/CommentController.php b/app/Activity/Controllers/CommentController.php index 479d57c4d..fd5463dff 100644 --- a/app/Activity/Controllers/CommentController.php +++ b/app/Activity/Controllers/CommentController.php @@ -7,6 +7,7 @@ use BookStack\Activity\Tools\CommentTree; use BookStack\Activity\Tools\CommentTreeNode; use BookStack\Entities\Queries\PageQueries; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use Illuminate\Http\Request; use Illuminate\Validation\ValidationException; @@ -42,7 +43,7 @@ class CommentController extends Controller } // Create a new comment. - $this->checkPermission('comment-create-all'); + $this->checkPermission(Permission::CommentCreateAll); $contentRef = $input['content_ref'] ?? ''; $comment = $this->commentRepo->create($page, $input['html'], $input['parent_id'] ?? null, $contentRef); @@ -64,8 +65,8 @@ class CommentController extends Controller ]); $comment = $this->commentRepo->getById($commentId); - $this->checkOwnablePermission('page-view', $comment->entity); - $this->checkOwnablePermission('comment-update', $comment); + $this->checkOwnablePermission(Permission::PageView, $comment->entity); + $this->checkOwnablePermission(Permission::CommentUpdate, $comment); $comment = $this->commentRepo->update($comment, $input['html']); @@ -81,8 +82,8 @@ class CommentController extends Controller public function archive(int $id) { $comment = $this->commentRepo->getById($id); - $this->checkOwnablePermission('page-view', $comment->entity); - if (!userCan('comment-update', $comment) && !userCan('comment-delete', $comment)) { + $this->checkOwnablePermission(Permission::PageView, $comment->entity); + if (!userCan(Permission::CommentUpdate, $comment) && !userCan(Permission::CommentDelete, $comment)) { $this->showPermissionError(); } @@ -101,8 +102,8 @@ class CommentController extends Controller public function unarchive(int $id) { $comment = $this->commentRepo->getById($id); - $this->checkOwnablePermission('page-view', $comment->entity); - if (!userCan('comment-update', $comment) && !userCan('comment-delete', $comment)) { + $this->checkOwnablePermission(Permission::PageView, $comment->entity); + if (!userCan(Permission::CommentUpdate, $comment) && !userCan(Permission::CommentDelete, $comment)) { $this->showPermissionError(); } @@ -121,7 +122,7 @@ class CommentController extends Controller public function destroy(int $id) { $comment = $this->commentRepo->getById($id); - $this->checkOwnablePermission('comment-delete', $comment); + $this->checkOwnablePermission(Permission::CommentDelete, $comment); $this->commentRepo->delete($comment); diff --git a/app/Activity/Controllers/WatchController.php b/app/Activity/Controllers/WatchController.php index 5df75da39..b77a893ea 100644 --- a/app/Activity/Controllers/WatchController.php +++ b/app/Activity/Controllers/WatchController.php @@ -5,13 +5,14 @@ namespace BookStack\Activity\Controllers; use BookStack\Activity\Tools\UserEntityWatchOptions; use BookStack\Entities\Tools\MixedEntityRequestHelper; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use Illuminate\Http\Request; class WatchController extends Controller { public function update(Request $request, MixedEntityRequestHelper $entityHelper) { - $this->checkPermission('receive-notifications'); + $this->checkPermission(Permission::ReceiveNotifications); $this->preventGuestAccess(); $requestData = $this->validate($request, array_merge([ diff --git a/app/Activity/Notifications/Handlers/BaseNotificationHandler.php b/app/Activity/Notifications/Handlers/BaseNotificationHandler.php index 3a9b0c1dc..bc6f2e22f 100644 --- a/app/Activity/Notifications/Handlers/BaseNotificationHandler.php +++ b/app/Activity/Notifications/Handlers/BaseNotificationHandler.php @@ -5,6 +5,7 @@ namespace BookStack\Activity\Notifications\Handlers; use BookStack\Activity\Models\Loggable; use BookStack\Activity\Notifications\Messages\BaseActivityNotification; use BookStack\Entities\Models\Entity; +use BookStack\Permissions\Permission; use BookStack\Permissions\PermissionApplicator; use BookStack\Users\Models\User; use Illuminate\Support\Facades\Log; @@ -26,7 +27,7 @@ abstract class BaseNotificationHandler implements NotificationHandler } // Prevent sending of the user does not have notification permissions - if (!$user->can('receive-notifications')) { + if (!$user->can(Permission::ReceiveNotifications)) { continue; } diff --git a/app/Activity/Tools/UserEntityWatchOptions.php b/app/Activity/Tools/UserEntityWatchOptions.php index 559d7903d..8e5f70758 100644 --- a/app/Activity/Tools/UserEntityWatchOptions.php +++ b/app/Activity/Tools/UserEntityWatchOptions.php @@ -7,6 +7,7 @@ use BookStack\Activity\WatchLevels; use BookStack\Entities\Models\BookChild; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; +use BookStack\Permissions\Permission; use BookStack\Users\Models\User; use Illuminate\Database\Eloquent\Builder; @@ -22,7 +23,7 @@ class UserEntityWatchOptions public function canWatch(): bool { - return $this->user->can('receive-notifications') && !$this->user->isGuest(); + return $this->user->can(Permission::ReceiveNotifications) && !$this->user->isGuest(); } public function getWatchLevel(): string diff --git a/app/Api/ApiTokenGuard.php b/app/Api/ApiTokenGuard.php index 6302884a9..9f4537b29 100644 --- a/app/Api/ApiTokenGuard.php +++ b/app/Api/ApiTokenGuard.php @@ -4,6 +4,7 @@ namespace BookStack\Api; use BookStack\Access\LoginService; use BookStack\Exceptions\ApiAuthException; +use BookStack\Permissions\Permission; use Illuminate\Auth\GuardHelpers; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Auth\Guard; @@ -146,7 +147,7 @@ class ApiTokenGuard implements Guard throw new ApiAuthException(trans('errors.api_user_token_expired'), 403); } - if (!$token->user->can('access-api')) { + if (!$token->user->can(Permission::AccessApi)) { throw new ApiAuthException(trans('errors.api_user_no_api_permission'), 403); } } diff --git a/app/Api/UserApiTokenController.php b/app/Api/UserApiTokenController.php index 3606e8260..2ca9e2235 100644 --- a/app/Api/UserApiTokenController.php +++ b/app/Api/UserApiTokenController.php @@ -4,6 +4,7 @@ namespace BookStack\Api; use BookStack\Activity\ActivityType; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Users\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; @@ -16,8 +17,8 @@ class UserApiTokenController extends Controller */ public function create(Request $request, int $userId) { - $this->checkPermission('access-api'); - $this->checkPermissionOrCurrentUser('users-manage', $userId); + $this->checkPermission(Permission::AccessApi); + $this->checkPermissionOrCurrentUser(Permission::UsersManage, $userId); $this->updateContext($request); $user = User::query()->findOrFail($userId); @@ -35,8 +36,8 @@ class UserApiTokenController extends Controller */ public function store(Request $request, int $userId) { - $this->checkPermission('access-api'); - $this->checkPermissionOrCurrentUser('users-manage', $userId); + $this->checkPermission(Permission::AccessApi); + $this->checkPermissionOrCurrentUser(Permission::UsersManage, $userId); $this->validate($request, [ 'name' => ['required', 'max:250'], @@ -143,8 +144,8 @@ class UserApiTokenController extends Controller */ protected function checkPermissionAndFetchUserToken(int $userId, int $tokenId): array { - $this->checkPermissionOr('users-manage', function () use ($userId) { - return $userId === user()->id && userCan('access-api'); + $this->checkPermissionOr(Permission::UsersManage, function () use ($userId) { + return $userId === user()->id && userCan(Permission::AccessApi); }); $user = User::query()->findOrFail($userId); diff --git a/app/App/helpers.php b/app/App/helpers.php index 0e26d9974..0e357e36a 100644 --- a/app/App/helpers.php +++ b/app/App/helpers.php @@ -56,7 +56,7 @@ function userCan(string|Permission $permission, ?Model $ownable = null): bool * Check if the current user can perform the given action on any items in the system. * Can be provided the class name of an entity to filter ability to that specific entity type. */ -function userCanOnAny(string $action, string $entityClass = ''): bool +function userCanOnAny(string|Permission $action, string $entityClass = ''): bool { $permissions = app()->make(PermissionApplicator::class); diff --git a/app/Entities/Controllers/BookApiController.php b/app/Entities/Controllers/BookApiController.php index a617ee2da..5baea163f 100644 --- a/app/Entities/Controllers/BookApiController.php +++ b/app/Entities/Controllers/BookApiController.php @@ -11,6 +11,7 @@ use BookStack\Entities\Queries\PageQueries; use BookStack\Entities\Repos\BookRepo; use BookStack\Entities\Tools\BookContents; use BookStack\Http\ApiController; +use BookStack\Permissions\Permission; use Illuminate\Http\Request; use Illuminate\Validation\ValidationException; @@ -47,7 +48,7 @@ class BookApiController extends ApiController */ public function create(Request $request) { - $this->checkPermission('book-create-all'); + $this->checkPermission(Permission::BookCreateAll); $requestData = $this->validate($request, $this->rules()['create']); $book = $this->bookRepo->create($requestData); @@ -92,7 +93,7 @@ class BookApiController extends ApiController public function update(Request $request, string $id) { $book = $this->queries->findVisibleByIdOrFail(intval($id)); - $this->checkOwnablePermission('book-update', $book); + $this->checkOwnablePermission(Permission::BookUpdate, $book); $requestData = $this->validate($request, $this->rules()['update']); $book = $this->bookRepo->update($book, $requestData); @@ -109,7 +110,7 @@ class BookApiController extends ApiController public function delete(string $id) { $book = $this->queries->findVisibleByIdOrFail(intval($id)); - $this->checkOwnablePermission('book-delete', $book); + $this->checkOwnablePermission(Permission::BookDelete, $book); $this->bookRepo->destroy($book); diff --git a/app/Entities/Controllers/BookController.php b/app/Entities/Controllers/BookController.php index 5d3d67f64..cbf7ffb79 100644 --- a/app/Entities/Controllers/BookController.php +++ b/app/Entities/Controllers/BookController.php @@ -17,6 +17,7 @@ use BookStack\Exceptions\ImageUploadException; use BookStack\Exceptions\NotFoundException; use BookStack\Facades\Activity; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\References\ReferenceFetcher; use BookStack\Util\DatabaseTransaction; use BookStack\Util\SimpleListOptions; @@ -73,12 +74,12 @@ class BookController extends Controller */ public function create(?string $shelfSlug = null) { - $this->checkPermission('book-create-all'); + $this->checkPermission(Permission::BookCreateAll); $bookshelf = null; if ($shelfSlug !== null) { $bookshelf = $this->shelfQueries->findVisibleBySlugOrFail($shelfSlug); - $this->checkOwnablePermission('bookshelf-update', $bookshelf); + $this->checkOwnablePermission(Permission::BookshelfUpdate, $bookshelf); } $this->setPageTitle(trans('entities.books_create')); @@ -96,7 +97,7 @@ class BookController extends Controller */ public function store(Request $request, ?string $shelfSlug = null) { - $this->checkPermission('book-create-all'); + $this->checkPermission(Permission::BookCreateAll); $validated = $this->validate($request, [ 'name' => ['required', 'string', 'max:255'], 'description_html' => ['string', 'max:2000'], @@ -108,7 +109,7 @@ class BookController extends Controller $bookshelf = null; if ($shelfSlug !== null) { $bookshelf = $this->shelfQueries->findVisibleBySlugOrFail($shelfSlug); - $this->checkOwnablePermission('bookshelf-update', $bookshelf); + $this->checkOwnablePermission(Permission::BookshelfUpdate, $bookshelf); } $book = $this->bookRepo->create($validated); @@ -154,7 +155,7 @@ class BookController extends Controller public function edit(string $slug) { $book = $this->queries->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('book-update', $book); + $this->checkOwnablePermission(Permission::BookUpdate, $book); $this->setPageTitle(trans('entities.books_edit_named', ['bookName' => $book->getShortName()])); return view('books.edit', ['book' => $book, 'current' => $book]); @@ -170,7 +171,7 @@ class BookController extends Controller public function update(Request $request, string $slug) { $book = $this->queries->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('book-update', $book); + $this->checkOwnablePermission(Permission::BookUpdate, $book); $validated = $this->validate($request, [ 'name' => ['required', 'string', 'max:255'], @@ -197,7 +198,7 @@ class BookController extends Controller public function showDelete(string $bookSlug) { $book = $this->queries->findVisibleBySlugOrFail($bookSlug); - $this->checkOwnablePermission('book-delete', $book); + $this->checkOwnablePermission(Permission::BookDelete, $book); $this->setPageTitle(trans('entities.books_delete_named', ['bookName' => $book->getShortName()])); return view('books.delete', ['book' => $book, 'current' => $book]); @@ -211,7 +212,7 @@ class BookController extends Controller public function destroy(string $bookSlug) { $book = $this->queries->findVisibleBySlugOrFail($bookSlug); - $this->checkOwnablePermission('book-delete', $book); + $this->checkOwnablePermission(Permission::BookDelete, $book); $this->bookRepo->destroy($book); @@ -226,7 +227,7 @@ class BookController extends Controller public function showCopy(string $bookSlug) { $book = $this->queries->findVisibleBySlugOrFail($bookSlug); - $this->checkOwnablePermission('book-view', $book); + $this->checkOwnablePermission(Permission::BookView, $book); session()->flashInput(['name' => $book->name]); @@ -243,8 +244,8 @@ class BookController extends Controller public function copy(Request $request, Cloner $cloner, string $bookSlug) { $book = $this->queries->findVisibleBySlugOrFail($bookSlug); - $this->checkOwnablePermission('book-view', $book); - $this->checkPermission('book-create-all'); + $this->checkOwnablePermission(Permission::BookView, $book); + $this->checkPermission(Permission::BookCreateAll); $newName = $request->get('name') ?: $book->name; $bookCopy = $cloner->cloneBook($book, $newName); @@ -259,10 +260,10 @@ class BookController extends Controller public function convertToShelf(HierarchyTransformer $transformer, string $bookSlug) { $book = $this->queries->findVisibleBySlugOrFail($bookSlug); - $this->checkOwnablePermission('book-update', $book); - $this->checkOwnablePermission('book-delete', $book); - $this->checkPermission('bookshelf-create-all'); - $this->checkPermission('book-create-all'); + $this->checkOwnablePermission(Permission::BookUpdate, $book); + $this->checkOwnablePermission(Permission::BookDelete, $book); + $this->checkPermission(Permission::BookshelfCreateAll); + $this->checkPermission(Permission::BookCreateAll); $shelf = (new DatabaseTransaction(function () use ($book, $transformer) { return $transformer->transformBookToShelf($book); diff --git a/app/Entities/Controllers/BookshelfApiController.php b/app/Entities/Controllers/BookshelfApiController.php index b512f2d05..f4bd394a9 100644 --- a/app/Entities/Controllers/BookshelfApiController.php +++ b/app/Entities/Controllers/BookshelfApiController.php @@ -6,6 +6,7 @@ use BookStack\Entities\Models\Bookshelf; use BookStack\Entities\Queries\BookshelfQueries; use BookStack\Entities\Repos\BookshelfRepo; use BookStack\Http\ApiController; +use BookStack\Permissions\Permission; use Exception; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Http\Request; @@ -45,7 +46,7 @@ class BookshelfApiController extends ApiController */ public function create(Request $request) { - $this->checkPermission('bookshelf-create-all'); + $this->checkPermission(Permission::BookshelfCreateAll); $requestData = $this->validate($request, $this->rules()['create']); $bookIds = $request->get('books', []); @@ -84,7 +85,7 @@ class BookshelfApiController extends ApiController public function update(Request $request, string $id) { $shelf = $this->queries->findVisibleByIdOrFail(intval($id)); - $this->checkOwnablePermission('bookshelf-update', $shelf); + $this->checkOwnablePermission(Permission::BookshelfUpdate, $shelf); $requestData = $this->validate($request, $this->rules()['update']); $bookIds = $request->get('books', null); @@ -103,7 +104,7 @@ class BookshelfApiController extends ApiController public function delete(string $id) { $shelf = $this->queries->findVisibleByIdOrFail(intval($id)); - $this->checkOwnablePermission('bookshelf-delete', $shelf); + $this->checkOwnablePermission(Permission::BookshelfDelete, $shelf); $this->bookshelfRepo->destroy($shelf); diff --git a/app/Entities/Controllers/BookshelfController.php b/app/Entities/Controllers/BookshelfController.php index 6cedd23e7..f47742ffa 100644 --- a/app/Entities/Controllers/BookshelfController.php +++ b/app/Entities/Controllers/BookshelfController.php @@ -11,6 +11,7 @@ use BookStack\Entities\Tools\ShelfContext; use BookStack\Exceptions\ImageUploadException; use BookStack\Exceptions\NotFoundException; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\References\ReferenceFetcher; use BookStack\Util\SimpleListOptions; use Exception; @@ -68,7 +69,7 @@ class BookshelfController extends Controller */ public function create() { - $this->checkPermission('bookshelf-create-all'); + $this->checkPermission(Permission::BookshelfCreateAll); $books = $this->bookQueries->visibleForList()->orderBy('name')->get(['name', 'id', 'slug', 'created_at', 'updated_at']); $this->setPageTitle(trans('entities.shelves_create')); @@ -83,7 +84,7 @@ class BookshelfController extends Controller */ public function store(Request $request) { - $this->checkPermission('bookshelf-create-all'); + $this->checkPermission(Permission::BookshelfCreateAll); $validated = $this->validate($request, [ 'name' => ['required', 'string', 'max:255'], 'description_html' => ['string', 'max:2000'], @@ -105,7 +106,7 @@ class BookshelfController extends Controller public function show(Request $request, ActivityQueries $activities, string $slug) { $shelf = $this->queries->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('bookshelf-view', $shelf); + $this->checkOwnablePermission(Permission::BookshelfView, $shelf); $listOptions = SimpleListOptions::fromRequest($request, 'shelf_books')->withSortOptions([ 'default' => trans('common.sort_default'), @@ -143,7 +144,7 @@ class BookshelfController extends Controller public function edit(string $slug) { $shelf = $this->queries->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('bookshelf-update', $shelf); + $this->checkOwnablePermission(Permission::BookshelfUpdate, $shelf); $shelfBookIds = $shelf->books()->get(['id'])->pluck('id'); $books = $this->bookQueries->visibleForList() @@ -169,7 +170,7 @@ class BookshelfController extends Controller public function update(Request $request, string $slug) { $shelf = $this->queries->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('bookshelf-update', $shelf); + $this->checkOwnablePermission(Permission::BookshelfUpdate, $shelf); $validated = $this->validate($request, [ 'name' => ['required', 'string', 'max:255'], 'description_html' => ['string', 'max:2000'], @@ -195,7 +196,7 @@ class BookshelfController extends Controller public function showDelete(string $slug) { $shelf = $this->queries->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('bookshelf-delete', $shelf); + $this->checkOwnablePermission(Permission::BookshelfDelete, $shelf); $this->setPageTitle(trans('entities.shelves_delete_named', ['name' => $shelf->getShortName()])); @@ -210,7 +211,7 @@ class BookshelfController extends Controller public function destroy(string $slug) { $shelf = $this->queries->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('bookshelf-delete', $shelf); + $this->checkOwnablePermission(Permission::BookshelfDelete, $shelf); $this->shelfRepo->destroy($shelf); diff --git a/app/Entities/Controllers/ChapterApiController.php b/app/Entities/Controllers/ChapterApiController.php index 6ba2e9fd2..80eab7bb8 100644 --- a/app/Entities/Controllers/ChapterApiController.php +++ b/app/Entities/Controllers/ChapterApiController.php @@ -9,6 +9,7 @@ use BookStack\Entities\Queries\EntityQueries; use BookStack\Entities\Repos\ChapterRepo; use BookStack\Exceptions\PermissionsException; use BookStack\Http\ApiController; +use BookStack\Permissions\Permission; use Exception; use Illuminate\Http\Request; @@ -65,7 +66,7 @@ class ChapterApiController extends ApiController $bookId = $request->get('book_id'); $book = $this->entityQueries->books->findVisibleByIdOrFail(intval($bookId)); - $this->checkOwnablePermission('chapter-create', $book); + $this->checkOwnablePermission(Permission::ChapterCreate, $book); $chapter = $this->chapterRepo->create($requestData, $book); @@ -101,10 +102,10 @@ class ChapterApiController extends ApiController { $requestData = $this->validate($request, $this->rules()['update']); $chapter = $this->queries->findVisibleByIdOrFail(intval($id)); - $this->checkOwnablePermission('chapter-update', $chapter); + $this->checkOwnablePermission(Permission::ChapterUpdate, $chapter); if ($request->has('book_id') && $chapter->book_id !== intval($requestData['book_id'])) { - $this->checkOwnablePermission('chapter-delete', $chapter); + $this->checkOwnablePermission(Permission::ChapterDelete, $chapter); try { $this->chapterRepo->move($chapter, "book:{$requestData['book_id']}"); @@ -129,7 +130,7 @@ class ChapterApiController extends ApiController public function delete(string $id) { $chapter = $this->queries->findVisibleByIdOrFail(intval($id)); - $this->checkOwnablePermission('chapter-delete', $chapter); + $this->checkOwnablePermission(Permission::ChapterDelete, $chapter); $this->chapterRepo->destroy($chapter); diff --git a/app/Entities/Controllers/ChapterController.php b/app/Entities/Controllers/ChapterController.php index 677745500..9335e0a70 100644 --- a/app/Entities/Controllers/ChapterController.php +++ b/app/Entities/Controllers/ChapterController.php @@ -17,6 +17,7 @@ use BookStack\Exceptions\NotFoundException; use BookStack\Exceptions\NotifyException; use BookStack\Exceptions\PermissionsException; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\References\ReferenceFetcher; use BookStack\Util\DatabaseTransaction; use Illuminate\Http\Request; @@ -39,7 +40,7 @@ class ChapterController extends Controller public function create(string $bookSlug) { $book = $this->entityQueries->books->findVisibleBySlugOrFail($bookSlug); - $this->checkOwnablePermission('chapter-create', $book); + $this->checkOwnablePermission(Permission::ChapterCreate, $book); $this->setPageTitle(trans('entities.chapters_create')); @@ -64,7 +65,7 @@ class ChapterController extends Controller ]); $book = $this->entityQueries->books->findVisibleBySlugOrFail($bookSlug); - $this->checkOwnablePermission('chapter-create', $book); + $this->checkOwnablePermission(Permission::ChapterCreate, $book); $chapter = $this->chapterRepo->create($validated, $book); @@ -77,7 +78,6 @@ class ChapterController extends Controller public function show(string $bookSlug, string $chapterSlug) { $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); - $this->checkOwnablePermission('chapter-view', $chapter); $sidebarTree = (new BookContents($chapter->book))->getTree(); $pages = $this->entityQueries->pages->visibleForChapterList($chapter->id)->get(); @@ -106,7 +106,7 @@ class ChapterController extends Controller public function edit(string $bookSlug, string $chapterSlug) { $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); - $this->checkOwnablePermission('chapter-update', $chapter); + $this->checkOwnablePermission(Permission::ChapterUpdate, $chapter); $this->setPageTitle(trans('entities.chapters_edit_named', ['chapterName' => $chapter->getShortName()])); @@ -128,7 +128,7 @@ class ChapterController extends Controller ]); $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); - $this->checkOwnablePermission('chapter-update', $chapter); + $this->checkOwnablePermission(Permission::ChapterUpdate, $chapter); $this->chapterRepo->update($chapter, $validated); @@ -143,7 +143,7 @@ class ChapterController extends Controller public function showDelete(string $bookSlug, string $chapterSlug) { $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); - $this->checkOwnablePermission('chapter-delete', $chapter); + $this->checkOwnablePermission(Permission::ChapterDelete, $chapter); $this->setPageTitle(trans('entities.chapters_delete_named', ['chapterName' => $chapter->getShortName()])); @@ -159,7 +159,7 @@ class ChapterController extends Controller public function destroy(string $bookSlug, string $chapterSlug) { $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); - $this->checkOwnablePermission('chapter-delete', $chapter); + $this->checkOwnablePermission(Permission::ChapterDelete, $chapter); $this->chapterRepo->destroy($chapter); @@ -175,8 +175,8 @@ class ChapterController extends Controller { $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); $this->setPageTitle(trans('entities.chapters_move_named', ['chapterName' => $chapter->getShortName()])); - $this->checkOwnablePermission('chapter-update', $chapter); - $this->checkOwnablePermission('chapter-delete', $chapter); + $this->checkOwnablePermission(Permission::ChapterUpdate, $chapter); + $this->checkOwnablePermission(Permission::ChapterDelete, $chapter); return view('chapters.move', [ 'chapter' => $chapter, @@ -192,8 +192,8 @@ class ChapterController extends Controller public function move(Request $request, string $bookSlug, string $chapterSlug) { $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); - $this->checkOwnablePermission('chapter-update', $chapter); - $this->checkOwnablePermission('chapter-delete', $chapter); + $this->checkOwnablePermission(Permission::ChapterUpdate, $chapter); + $this->checkOwnablePermission(Permission::ChapterDelete, $chapter); $entitySelection = $request->get('entity_selection', null); if ($entitySelection === null || $entitySelection === '') { @@ -221,7 +221,6 @@ class ChapterController extends Controller public function showCopy(string $bookSlug, string $chapterSlug) { $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); - $this->checkOwnablePermission('chapter-view', $chapter); session()->flashInput(['name' => $chapter->name]); @@ -240,7 +239,6 @@ class ChapterController extends Controller public function copy(Request $request, Cloner $cloner, string $bookSlug, string $chapterSlug) { $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); - $this->checkOwnablePermission('chapter-view', $chapter); $entitySelection = $request->get('entity_selection') ?: null; $newParentBook = $entitySelection ? $this->entityQueries->findVisibleByStringIdentifier($entitySelection) : $chapter->getParent(); @@ -251,7 +249,7 @@ class ChapterController extends Controller return redirect($chapter->getUrl('/copy')); } - $this->checkOwnablePermission('chapter-create', $newParentBook); + $this->checkOwnablePermission(Permission::ChapterCreate, $newParentBook); $newName = $request->get('name') ?: $chapter->name; $chapterCopy = $cloner->cloneChapter($chapter, $newParentBook, $newName); @@ -266,9 +264,9 @@ class ChapterController extends Controller public function convertToBook(HierarchyTransformer $transformer, string $bookSlug, string $chapterSlug) { $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); - $this->checkOwnablePermission('chapter-update', $chapter); - $this->checkOwnablePermission('chapter-delete', $chapter); - $this->checkPermission('book-create-all'); + $this->checkOwnablePermission(Permission::ChapterUpdate, $chapter); + $this->checkOwnablePermission(Permission::ChapterDelete, $chapter); + $this->checkPermission(Permission::BookCreateAll); $book = (new DatabaseTransaction(function () use ($chapter, $transformer) { return $transformer->transformChapterToBook($chapter); diff --git a/app/Entities/Controllers/PageApiController.php b/app/Entities/Controllers/PageApiController.php index 8fcba3dc6..033c19a7a 100644 --- a/app/Entities/Controllers/PageApiController.php +++ b/app/Entities/Controllers/PageApiController.php @@ -7,6 +7,7 @@ use BookStack\Entities\Queries\PageQueries; use BookStack\Entities\Repos\PageRepo; use BookStack\Exceptions\PermissionsException; use BookStack\Http\ApiController; +use BookStack\Permissions\Permission; use Exception; use Illuminate\Http\Request; @@ -76,7 +77,7 @@ class PageApiController extends ApiController } else { $parent = $this->entityQueries->books->findVisibleByIdOrFail(intval($request->get('book_id'))); } - $this->checkOwnablePermission('page-create', $parent); + $this->checkOwnablePermission(Permission::PageCreate, $parent); $draft = $this->pageRepo->getNewDraftPage($parent); $this->pageRepo->publishDraft($draft, $request->only(array_keys($this->rules['create']))); @@ -116,7 +117,7 @@ class PageApiController extends ApiController $requestData = $this->validate($request, $this->rules['update']); $page = $this->queries->findVisibleByIdOrFail($id); - $this->checkOwnablePermission('page-update', $page); + $this->checkOwnablePermission(Permission::PageUpdate, $page); $parent = null; if ($request->has('chapter_id')) { @@ -126,7 +127,7 @@ class PageApiController extends ApiController } if ($parent && !$parent->matches($page->getParent())) { - $this->checkOwnablePermission('page-delete', $page); + $this->checkOwnablePermission(Permission::PageDelete, $page); try { $this->pageRepo->move($page, $parent->getType() . ':' . $parent->id); @@ -151,7 +152,7 @@ class PageApiController extends ApiController public function delete(string $id) { $page = $this->queries->findVisibleByIdOrFail($id); - $this->checkOwnablePermission('page-delete', $page); + $this->checkOwnablePermission(Permission::PageDelete, $page); $this->pageRepo->destroy($page); diff --git a/app/Entities/Controllers/PageController.php b/app/Entities/Controllers/PageController.php index de3aed7d9..d4bde300b 100644 --- a/app/Entities/Controllers/PageController.php +++ b/app/Entities/Controllers/PageController.php @@ -20,6 +20,7 @@ use BookStack\Exceptions\NotFoundException; use BookStack\Exceptions\NotifyException; use BookStack\Exceptions\PermissionsException; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\References\ReferenceFetcher; use Exception; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -50,7 +51,7 @@ class PageController extends Controller $parent = $this->entityQueries->books->findVisibleBySlugOrFail($bookSlug); } - $this->checkOwnablePermission('page-create', $parent); + $this->checkOwnablePermission(Permission::PageCreate, $parent); // Redirect to draft edit screen if signed in if ($this->isSignedIn()) { @@ -82,7 +83,7 @@ class PageController extends Controller $parent = $this->entityQueries->books->findVisibleBySlugOrFail($bookSlug); } - $this->checkOwnablePermission('page-create', $parent); + $this->checkOwnablePermission(Permission::PageCreate, $parent); $page = $this->pageRepo->getNewDraftPage($parent); $this->pageRepo->publishDraft($page, [ @@ -100,7 +101,7 @@ class PageController extends Controller public function editDraft(Request $request, string $bookSlug, int $pageId) { $draft = $this->queries->findVisibleByIdOrFail($pageId); - $this->checkOwnablePermission('page-create', $draft->getParent()); + $this->checkOwnablePermission(Permission::PageCreate, $draft->getParent()); $editorData = new PageEditorData($draft, $this->entityQueries, $request->query('editor', '')); $this->setPageTitle(trans('entities.pages_edit_draft')); @@ -120,7 +121,7 @@ class PageController extends Controller 'name' => ['required', 'string', 'max:255'], ]); $draftPage = $this->queries->findVisibleByIdOrFail($pageId); - $this->checkOwnablePermission('page-create', $draftPage->getParent()); + $this->checkOwnablePermission(Permission::PageCreate, $draftPage->getParent()); $page = $this->pageRepo->publishDraft($draftPage, $request->all()); @@ -148,8 +149,6 @@ class PageController extends Controller return redirect($page->getUrl()); } - $this->checkOwnablePermission('page-view', $page); - $pageContent = (new PageContent($page)); $page->html = $pageContent->render(); $pageNav = $pageContent->getNavigation($page->html); @@ -197,7 +196,7 @@ class PageController extends Controller public function edit(Request $request, string $bookSlug, string $pageSlug) { $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('page-update', $page, $page->getUrl()); + $this->checkOwnablePermission(Permission::PageUpdate, $page, $page->getUrl()); $editorData = new PageEditorData($page, $this->entityQueries, $request->query('editor', '')); if ($editorData->getWarnings()) { @@ -221,7 +220,7 @@ class PageController extends Controller 'name' => ['required', 'string', 'max:255'], ]); $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('page-update', $page); + $this->checkOwnablePermission(Permission::PageUpdate, $page); $this->pageRepo->update($page, $request->all()); @@ -236,7 +235,7 @@ class PageController extends Controller public function saveDraft(Request $request, int $pageId) { $page = $this->queries->findVisibleByIdOrFail($pageId); - $this->checkOwnablePermission('page-update', $page); + $this->checkOwnablePermission(Permission::PageUpdate, $page); if (!$this->isSignedIn()) { return $this->jsonError(trans('errors.guests_cannot_save_drafts'), 500); @@ -273,7 +272,7 @@ class PageController extends Controller public function showDelete(string $bookSlug, string $pageSlug) { $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('page-delete', $page); + $this->checkOwnablePermission(Permission::PageDelete, $page); $this->setPageTitle(trans('entities.pages_delete_named', ['pageName' => $page->getShortName()])); $usedAsTemplate = $this->entityQueries->books->start()->where('default_template_id', '=', $page->id)->count() > 0 || @@ -295,7 +294,7 @@ class PageController extends Controller public function showDeleteDraft(string $bookSlug, int $pageId) { $page = $this->queries->findVisibleByIdOrFail($pageId); - $this->checkOwnablePermission('page-update', $page); + $this->checkOwnablePermission(Permission::PageUpdate, $page); $this->setPageTitle(trans('entities.pages_delete_draft_named', ['pageName' => $page->getShortName()])); $usedAsTemplate = $this->entityQueries->books->start()->where('default_template_id', '=', $page->id)->count() > 0 || @@ -318,7 +317,7 @@ class PageController extends Controller public function destroy(string $bookSlug, string $pageSlug) { $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('page-delete', $page); + $this->checkOwnablePermission(Permission::PageDelete, $page); $parent = $page->getParent(); $this->pageRepo->destroy($page); @@ -337,7 +336,7 @@ class PageController extends Controller $page = $this->queries->findVisibleByIdOrFail($pageId); $book = $page->book; $chapter = $page->chapter; - $this->checkOwnablePermission('page-update', $page); + $this->checkOwnablePermission(Permission::PageUpdate, $page); $this->pageRepo->destroy($page); @@ -384,8 +383,8 @@ class PageController extends Controller public function showMove(string $bookSlug, string $pageSlug) { $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('page-update', $page); - $this->checkOwnablePermission('page-delete', $page); + $this->checkOwnablePermission(Permission::PageUpdate, $page); + $this->checkOwnablePermission(Permission::PageDelete, $page); return view('pages.move', [ 'book' => $page->book, @@ -402,8 +401,8 @@ class PageController extends Controller public function move(Request $request, string $bookSlug, string $pageSlug) { $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('page-update', $page); - $this->checkOwnablePermission('page-delete', $page); + $this->checkOwnablePermission(Permission::PageUpdate, $page); + $this->checkOwnablePermission(Permission::PageDelete, $page); $entitySelection = $request->get('entity_selection', null); if ($entitySelection === null || $entitySelection === '') { @@ -431,7 +430,6 @@ class PageController extends Controller public function showCopy(string $bookSlug, string $pageSlug) { $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('page-view', $page); session()->flashInput(['name' => $page->name]); return view('pages.copy', [ @@ -449,7 +447,7 @@ class PageController extends Controller public function copy(Request $request, Cloner $cloner, string $bookSlug, string $pageSlug) { $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('page-view', $page); + $this->checkOwnablePermission(Permission::PageView, $page); $entitySelection = $request->get('entity_selection') ?: null; $newParent = $entitySelection ? $this->entityQueries->findVisibleByStringIdentifier($entitySelection) : $page->getParent(); @@ -460,7 +458,7 @@ class PageController extends Controller return redirect($page->getUrl('/copy')); } - $this->checkOwnablePermission('page-create', $newParent); + $this->checkOwnablePermission(Permission::PageCreate, $newParent); $newName = $request->get('name') ?: $page->name; $pageCopy = $cloner->clonePage($page, $newParent, $newName); diff --git a/app/Entities/Controllers/PageRevisionController.php b/app/Entities/Controllers/PageRevisionController.php index c43eea08b..35f1e8daf 100644 --- a/app/Entities/Controllers/PageRevisionController.php +++ b/app/Entities/Controllers/PageRevisionController.php @@ -11,6 +11,7 @@ use BookStack\Entities\Tools\PageContent; use BookStack\Exceptions\NotFoundException; use BookStack\Facades\Activity; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Util\SimpleListOptions; use Illuminate\Http\Request; use Ssddanbrown\HtmlDiff\Diff; @@ -124,7 +125,7 @@ class PageRevisionController extends Controller public function restore(string $bookSlug, string $pageSlug, int $revisionId) { $page = $this->pageQueries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('page-update', $page); + $this->checkOwnablePermission(Permission::PageUpdate, $page); $page = $this->pageRepo->restoreRevision($page, $revisionId); @@ -139,7 +140,7 @@ class PageRevisionController extends Controller public function destroy(string $bookSlug, string $pageSlug, int $revId) { $page = $this->pageQueries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('page-delete', $page); + $this->checkOwnablePermission(Permission::PageDelete, $page); $revision = $page->revisions()->where('id', '=', $revId)->first(); if ($revision === null) { diff --git a/app/Entities/Controllers/RecycleBinApiController.php b/app/Entities/Controllers/RecycleBinApiController.php index 89bd3f41a..614685136 100644 --- a/app/Entities/Controllers/RecycleBinApiController.php +++ b/app/Entities/Controllers/RecycleBinApiController.php @@ -9,6 +9,7 @@ use BookStack\Entities\Models\Deletion; use BookStack\Entities\Models\Page; use BookStack\Entities\Repos\DeletionRepo; use BookStack\Http\ApiController; +use BookStack\Permissions\Permission; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -17,8 +18,8 @@ class RecycleBinApiController extends ApiController public function __construct() { $this->middleware(function ($request, $next) { - $this->checkPermission('settings-manage'); - $this->checkPermission('restrictions-manage-all'); + $this->checkPermission(Permission::SettingsManage); + $this->checkPermission(Permission::RestrictionsManageAll); return $next($request); }); diff --git a/app/Entities/Controllers/RecycleBinController.php b/app/Entities/Controllers/RecycleBinController.php index d11dde4dd..f3c2b6a01 100644 --- a/app/Entities/Controllers/RecycleBinController.php +++ b/app/Entities/Controllers/RecycleBinController.php @@ -8,6 +8,7 @@ use BookStack\Entities\Models\Entity; use BookStack\Entities\Repos\DeletionRepo; use BookStack\Entities\Tools\TrashCan; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; class RecycleBinController extends Controller { @@ -20,8 +21,8 @@ class RecycleBinController extends Controller public function __construct() { $this->middleware(function ($request, $next) { - $this->checkPermission('settings-manage'); - $this->checkPermission('restrictions-manage-all'); + $this->checkPermission(Permission::SettingsManage); + $this->checkPermission(Permission::RestrictionsManageAll); return $next($request); }); diff --git a/app/Entities/Tools/PageContent.php b/app/Entities/Tools/PageContent.php index d2f5de65c..4b1d77db7 100644 --- a/app/Entities/Tools/PageContent.php +++ b/app/Entities/Tools/PageContent.php @@ -7,6 +7,7 @@ use BookStack\Entities\Queries\PageQueries; use BookStack\Entities\Tools\Markdown\MarkdownToHtml; use BookStack\Exceptions\ImageUploadException; use BookStack\Facades\Theme; +use BookStack\Permissions\Permission; use BookStack\Theming\ThemeEvents; use BookStack\Uploads\ImageRepo; use BookStack\Uploads\ImageService; @@ -122,7 +123,7 @@ class PageContent $imageInfo = $this->parseBase64ImageUri($uri); // Validate user has permission to create images - if (!$updater->can('image-create-all')) { + if (!$updater->can(Permission::ImageCreateAll)) { return ''; } diff --git a/app/Http/Middleware/ApiAuthenticate.php b/app/Http/Middleware/ApiAuthenticate.php index 5f3ad3168..15b5a325a 100644 --- a/app/Http/Middleware/ApiAuthenticate.php +++ b/app/Http/Middleware/ApiAuthenticate.php @@ -3,6 +3,7 @@ namespace BookStack\Http\Middleware; use BookStack\Exceptions\ApiAuthException; +use BookStack\Permissions\Permission; use Closure; use Illuminate\Http\Request; @@ -51,7 +52,7 @@ class ApiAuthenticate */ protected function sessionUserHasApiAccess(): bool { - $hasApiPermission = user()->can('access-api'); + $hasApiPermission = user()->can(Permission::AccessApi); return $hasApiPermission && user()->hasAppAccess(); } diff --git a/app/Http/Middleware/CheckUserHasPermission.php b/app/Http/Middleware/CheckUserHasPermission.php index b5678e734..ea4ff652a 100644 --- a/app/Http/Middleware/CheckUserHasPermission.php +++ b/app/Http/Middleware/CheckUserHasPermission.php @@ -2,6 +2,7 @@ namespace BookStack\Http\Middleware; +use BookStack\Permissions\Permission; use Closure; use Illuminate\Http\Request; @@ -10,13 +11,9 @@ class CheckUserHasPermission /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param string $permission - * * @return mixed */ - public function handle($request, Closure $next, $permission) + public function handle(Request $request, Closure $next, string|Permission $permission) { if (!user()->can($permission)) { return $this->errorResponse($request); diff --git a/app/Permissions/ContentPermissionApiController.php b/app/Permissions/ContentPermissionApiController.php index bddbc2c7d..0720cc478 100644 --- a/app/Permissions/ContentPermissionApiController.php +++ b/app/Permissions/ContentPermissionApiController.php @@ -51,7 +51,7 @@ class ContentPermissionApiController extends ApiController $entity = $this->entities->get($contentType) ->newQuery()->scopes(['visible'])->findOrFail($contentId); - $this->checkOwnablePermission('restrictions-manage', $entity); + $this->checkOwnablePermission(Permission::RestrictionsManage, $entity); return response()->json($this->formattedPermissionDataForEntity($entity)); } @@ -71,7 +71,7 @@ class ContentPermissionApiController extends ApiController $entity = $this->entities->get($contentType) ->newQuery()->scopes(['visible'])->findOrFail($contentId); - $this->checkOwnablePermission('restrictions-manage', $entity); + $this->checkOwnablePermission(Permission::RestrictionsManage, $entity); $data = $this->validate($request, $this->rules()['update']); $this->permissionsUpdater->updateFromApiRequestData($entity, $data); diff --git a/app/Permissions/Permission.php b/app/Permissions/Permission.php index 539bbe808..492ca2621 100644 --- a/app/Permissions/Permission.php +++ b/app/Permissions/Permission.php @@ -10,6 +10,9 @@ namespace BookStack\Permissions; * We use and still allow the string values in usage to allow for compatibility with scenarios where * users have customised their instance with additional permissions via the theme system. * This enum primarily exists for alignment within the codebase. + * + * Permissions with all/own suffixes may also be represented as a higher-level alias without the own/all + * suffix, which are used and assessed in the permission system logic. */ enum Permission: string { @@ -26,6 +29,7 @@ enum Permission: string case ContentImport = 'content-import'; case EditorChange = 'editor-change'; case ReceiveNotifications = 'receive-notifications'; + case RestrictionsManage = 'restrictions-manage'; case RestrictionsManageAll = 'restrictions-manage-all'; case RestrictionsManageOwn = 'restrictions-manage-own'; case SettingsManage = 'settings-manage'; @@ -33,33 +37,46 @@ enum Permission: string case UserRolesManage = 'user-roles-manage'; case UsersManage = 'users-manage'; - // Entity permissions - // Each has 'all' or 'own' in it's RolePermission, with the base non-suffix name being used - // in actual checking logic, with the permission system handling the assessment of the underlying RolePermission. + // Non-entity content permissions case AttachmentCreate = 'attachment-create'; case AttachmentCreateAll = 'attachment-create-all'; case AttachmentCreateOwn = 'attachment-create-own'; - case AttachmentDelete = 'attachment-delete'; case AttachmentDeleteAll = 'attachment-delete-all'; case AttachmentDeleteOwn = 'attachment-delete-own'; - case AttachmentUpdate = 'attachment-update'; case AttachmentUpdateAll = 'attachment-update-all'; case AttachmentUpdateOwn = 'attachment-update-own'; + case CommentCreate = 'comment-create'; + case CommentCreateAll = 'comment-create-all'; + case CommentCreateOwn = 'comment-create-own'; + case CommentDelete = 'comment-delete'; + case CommentDeleteAll = 'comment-delete-all'; + case CommentDeleteOwn = 'comment-delete-own'; + case CommentUpdate = 'comment-update'; + case CommentUpdateAll = 'comment-update-all'; + case CommentUpdateOwn = 'comment-update-own'; + + case ImageCreateAll = 'image-create-all'; + case ImageCreateOwn = 'image-create-own'; + case ImageDelete = 'image-delete'; + case ImageDeleteAll = 'image-delete-all'; + case ImageDeleteOwn = 'image-delete-own'; + case ImageUpdate = 'image-update'; + case ImageUpdateAll = 'image-update-all'; + case ImageUpdateOwn = 'image-update-own'; + + // Entity content permissions case BookCreate = 'book-create'; case BookCreateAll = 'book-create-all'; case BookCreateOwn = 'book-create-own'; - case BookDelete = 'book-delete'; case BookDeleteAll = 'book-delete-all'; case BookDeleteOwn = 'book-delete-own'; - case BookUpdate = 'book-update'; case BookUpdateAll = 'book-update-all'; case BookUpdateOwn = 'book-update-own'; - case BookView = 'book-view'; case BookViewAll = 'book-view-all'; case BookViewOwn = 'book-view-own'; @@ -67,15 +84,12 @@ enum Permission: string case BookshelfCreate = 'bookshelf-create'; case BookshelfCreateAll = 'bookshelf-create-all'; case BookshelfCreateOwn = 'bookshelf-create-own'; - case BookshelfDelete = 'bookshelf-delete'; case BookshelfDeleteAll = 'bookshelf-delete-all'; case BookshelfDeleteOwn = 'bookshelf-delete-own'; - case BookshelfUpdate = 'bookshelf-update'; case BookshelfUpdateAll = 'bookshelf-update-all'; case BookshelfUpdateOwn = 'bookshelf-update-own'; - case BookshelfView = 'bookshelf-view'; case BookshelfViewAll = 'bookshelf-view-all'; case BookshelfViewOwn = 'bookshelf-view-own'; @@ -83,55 +97,25 @@ enum Permission: string case ChapterCreate = 'chapter-create'; case ChapterCreateAll = 'chapter-create-all'; case ChapterCreateOwn = 'chapter-create-own'; - case ChapterDelete = 'chapter-delete'; case ChapterDeleteAll = 'chapter-delete-all'; case ChapterDeleteOwn = 'chapter-delete-own'; - case ChapterUpdate = 'chapter-update'; case ChapterUpdateAll = 'chapter-update-all'; case ChapterUpdateOwn = 'chapter-update-own'; - case ChapterView = 'chapter-view'; case ChapterViewAll = 'chapter-view-all'; case ChapterViewOwn = 'chapter-view-own'; - case CommentCreate = 'comment-create'; - case CommentCreateAll = 'comment-create-all'; - case CommentCreateOwn = 'comment-create-own'; - - case CommentDelete = 'comment-delete'; - case CommentDeleteAll = 'comment-delete-all'; - case CommentDeleteOwn = 'comment-delete-own'; - - case CommentUpdate = 'comment-update'; - case CommentUpdateAll = 'comment-update-all'; - case CommentUpdateOwn = 'comment-update-own'; - - case ImageCreate = 'image-create'; - case ImageCreateAll = 'image-create-all'; - case ImageCreateOwn = 'image-create-own'; - - case ImageDelete = 'image-delete'; - case ImageDeleteAll = 'image-delete-all'; - case ImageDeleteOwn = 'image-delete-own'; - - case ImageUpdate = 'image-update'; - case ImageUpdateAll = 'image-update-all'; - case ImageUpdateOwn = 'image-update-own'; - case PageCreate = 'page-create'; case PageCreateAll = 'page-create-all'; case PageCreateOwn = 'page-create-own'; - case PageDelete = 'page-delete'; case PageDeleteAll = 'page-delete-all'; case PageDeleteOwn = 'page-delete-own'; - case PageUpdate = 'page-update'; case PageUpdateAll = 'page-update-all'; case PageUpdateOwn = 'page-update-own'; - case PageView = 'page-view'; case PageViewAll = 'page-view-all'; case PageViewOwn = 'page-view-own'; diff --git a/app/Permissions/PermissionsController.php b/app/Permissions/PermissionsController.php index 9dcfe242e..d93d9e718 100644 --- a/app/Permissions/PermissionsController.php +++ b/app/Permissions/PermissionsController.php @@ -24,7 +24,7 @@ class PermissionsController extends Controller public function showForPage(string $bookSlug, string $pageSlug) { $page = $this->queries->pages->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('restrictions-manage', $page); + $this->checkOwnablePermission(Permission::RestrictionsManage, $page); $this->setPageTitle(trans('entities.pages_permissions')); return view('pages.permissions', [ @@ -39,7 +39,7 @@ class PermissionsController extends Controller public function updateForPage(Request $request, string $bookSlug, string $pageSlug) { $page = $this->queries->pages->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $this->checkOwnablePermission('restrictions-manage', $page); + $this->checkOwnablePermission(Permission::RestrictionsManage, $page); (new DatabaseTransaction(function () use ($page, $request) { $this->permissionsUpdater->updateFromPermissionsForm($page, $request); @@ -56,7 +56,7 @@ class PermissionsController extends Controller public function showForChapter(string $bookSlug, string $chapterSlug) { $chapter = $this->queries->chapters->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); - $this->checkOwnablePermission('restrictions-manage', $chapter); + $this->checkOwnablePermission(Permission::RestrictionsManage, $chapter); $this->setPageTitle(trans('entities.chapters_permissions')); return view('chapters.permissions', [ @@ -71,7 +71,7 @@ class PermissionsController extends Controller public function updateForChapter(Request $request, string $bookSlug, string $chapterSlug) { $chapter = $this->queries->chapters->findVisibleBySlugsOrFail($bookSlug, $chapterSlug); - $this->checkOwnablePermission('restrictions-manage', $chapter); + $this->checkOwnablePermission(Permission::RestrictionsManage, $chapter); (new DatabaseTransaction(function () use ($chapter, $request) { $this->permissionsUpdater->updateFromPermissionsForm($chapter, $request); @@ -88,7 +88,7 @@ class PermissionsController extends Controller public function showForBook(string $slug) { $book = $this->queries->books->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('restrictions-manage', $book); + $this->checkOwnablePermission(Permission::RestrictionsManage, $book); $this->setPageTitle(trans('entities.books_permissions')); return view('books.permissions', [ @@ -103,7 +103,7 @@ class PermissionsController extends Controller public function updateForBook(Request $request, string $slug) { $book = $this->queries->books->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('restrictions-manage', $book); + $this->checkOwnablePermission(Permission::RestrictionsManage, $book); (new DatabaseTransaction(function () use ($book, $request) { $this->permissionsUpdater->updateFromPermissionsForm($book, $request); @@ -120,7 +120,7 @@ class PermissionsController extends Controller public function showForShelf(string $slug) { $shelf = $this->queries->shelves->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('restrictions-manage', $shelf); + $this->checkOwnablePermission(Permission::RestrictionsManage, $shelf); $this->setPageTitle(trans('entities.shelves_permissions')); return view('shelves.permissions', [ @@ -135,7 +135,7 @@ class PermissionsController extends Controller public function updateForShelf(Request $request, string $slug) { $shelf = $this->queries->shelves->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('restrictions-manage', $shelf); + $this->checkOwnablePermission(Permission::RestrictionsManage, $shelf); (new DatabaseTransaction(function () use ($shelf, $request) { $this->permissionsUpdater->updateFromPermissionsForm($shelf, $request); @@ -152,7 +152,7 @@ class PermissionsController extends Controller public function copyShelfPermissionsToBooks(string $slug) { $shelf = $this->queries->shelves->findVisibleBySlugOrFail($slug); - $this->checkOwnablePermission('restrictions-manage', $shelf); + $this->checkOwnablePermission(Permission::RestrictionsManage, $shelf); $updateCount = (new DatabaseTransaction(function () use ($shelf) { return $this->permissionsUpdater->updateBookPermissionsFromShelf($shelf); @@ -168,7 +168,7 @@ class PermissionsController extends Controller */ public function formRowForRole(string $entityType, string $roleId) { - $this->checkPermissionOr('restrictions-manage-all', fn() => userCan('restrictions-manage-own')); + $this->checkPermissionOr(Permission::RestrictionsManageAll, fn() => userCan(Permission::RestrictionsManageOwn)); $role = Role::query()->findOrFail($roleId); diff --git a/app/Settings/MaintenanceController.php b/app/Settings/MaintenanceController.php index ac9dd20cc..b2b2226bf 100644 --- a/app/Settings/MaintenanceController.php +++ b/app/Settings/MaintenanceController.php @@ -6,6 +6,7 @@ use BookStack\Activity\ActivityType; use BookStack\App\AppVersion; use BookStack\Entities\Tools\TrashCan; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\References\ReferenceStore; use BookStack\Uploads\ImageService; use Illuminate\Http\Request; @@ -17,7 +18,7 @@ class MaintenanceController extends Controller */ public function index(TrashCan $trashCan) { - $this->checkPermission('settings-manage'); + $this->checkPermission(Permission::SettingsManage); $this->setPageTitle(trans('settings.maint')); // Recycle bin details @@ -34,7 +35,7 @@ class MaintenanceController extends Controller */ public function cleanupImages(Request $request, ImageService $imageService) { - $this->checkPermission('settings-manage'); + $this->checkPermission(Permission::SettingsManage); $this->logActivity(ActivityType::MAINTENANCE_ACTION_RUN, 'cleanup-images'); $checkRevisions = !($request->get('ignore_revisions', 'false') === 'true'); @@ -62,7 +63,7 @@ class MaintenanceController extends Controller */ public function sendTestEmail() { - $this->checkPermission('settings-manage'); + $this->checkPermission(Permission::SettingsManage); $this->logActivity(ActivityType::MAINTENANCE_ACTION_RUN, 'send-test-email'); try { @@ -81,7 +82,7 @@ class MaintenanceController extends Controller */ public function regenerateReferences(ReferenceStore $referenceStore) { - $this->checkPermission('settings-manage'); + $this->checkPermission(Permission::SettingsManage); $this->logActivity(ActivityType::MAINTENANCE_ACTION_RUN, 'regenerate-references'); try { diff --git a/app/Settings/SettingController.php b/app/Settings/SettingController.php index 3b7ba74d5..f89bc6dab 100644 --- a/app/Settings/SettingController.php +++ b/app/Settings/SettingController.php @@ -5,6 +5,7 @@ namespace BookStack\Settings; use BookStack\Activity\ActivityType; use BookStack\App\AppVersion; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Users\Models\User; use Illuminate\Http\Request; @@ -24,7 +25,7 @@ class SettingController extends Controller public function category(string $category) { $this->ensureCategoryExists($category); - $this->checkPermission('settings-manage'); + $this->checkPermission(Permission::SettingsManage); $this->setPageTitle(trans('settings.settings')); return view('settings.categories.' . $category, [ @@ -41,7 +42,7 @@ class SettingController extends Controller { $this->ensureCategoryExists($category); $this->preventAccessInDemoMode(); - $this->checkPermission('settings-manage'); + $this->checkPermission(Permission::SettingsManage); $this->validate($request, [ 'app_logo' => ['nullable', ...$this->getImageValidationRules()], 'app_icon' => ['nullable', ...$this->getImageValidationRules()], diff --git a/app/Sorting/BookSortController.php b/app/Sorting/BookSortController.php index d70d0e656..7e2ee5465 100644 --- a/app/Sorting/BookSortController.php +++ b/app/Sorting/BookSortController.php @@ -7,6 +7,7 @@ use BookStack\Entities\Queries\BookQueries; use BookStack\Entities\Tools\BookContents; use BookStack\Facades\Activity; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Util\DatabaseTransaction; use Illuminate\Http\Request; @@ -23,7 +24,7 @@ class BookSortController extends Controller public function show(string $bookSlug) { $book = $this->queries->findVisibleBySlugOrFail($bookSlug); - $this->checkOwnablePermission('book-update', $book); + $this->checkOwnablePermission(Permission::BookUpdate, $book); $bookChildren = (new BookContents($book))->getTree(false); @@ -51,7 +52,7 @@ class BookSortController extends Controller public function update(Request $request, BookSorter $sorter, string $bookSlug) { $book = $this->queries->findVisibleBySlugOrFail($bookSlug); - $this->checkOwnablePermission('book-update', $book); + $this->checkOwnablePermission(Permission::BookUpdate, $book); $loggedActivityForBook = false; // Sort via map diff --git a/app/Uploads/Controllers/AttachmentApiController.php b/app/Uploads/Controllers/AttachmentApiController.php index 87e00257c..b47d6ff8d 100644 --- a/app/Uploads/Controllers/AttachmentApiController.php +++ b/app/Uploads/Controllers/AttachmentApiController.php @@ -5,6 +5,7 @@ namespace BookStack\Uploads\Controllers; use BookStack\Entities\Queries\PageQueries; use BookStack\Exceptions\FileUploadException; use BookStack\Http\ApiController; +use BookStack\Permissions\Permission; use BookStack\Uploads\Attachment; use BookStack\Uploads\AttachmentService; use Exception; @@ -45,12 +46,12 @@ class AttachmentApiController extends ApiController */ public function create(Request $request) { - $this->checkPermission('attachment-create-all'); + $this->checkPermission(Permission::AttachmentCreateAll); $requestData = $this->validate($request, $this->rules()['create']); $pageId = $request->get('uploaded_to'); $page = $this->pageQueries->findVisibleByIdOrFail($pageId); - $this->checkOwnablePermission('page-update', $page); + $this->checkOwnablePermission(Permission::PageUpdate, $page); if ($request->hasFile('file')) { $uploadedFile = $request->file('file'); @@ -137,9 +138,9 @@ class AttachmentApiController extends ApiController $attachment->uploaded_to = $requestData['uploaded_to']; } - $this->checkOwnablePermission('page-view', $page); - $this->checkOwnablePermission('page-update', $page); - $this->checkOwnablePermission('attachment-update', $attachment); + $this->checkOwnablePermission(Permission::PageView, $page); + $this->checkOwnablePermission(Permission::PageUpdate, $page); + $this->checkOwnablePermission(Permission::AttachmentUpdate, $attachment); if ($request->hasFile('file')) { $uploadedFile = $request->file('file'); @@ -160,7 +161,7 @@ class AttachmentApiController extends ApiController { /** @var Attachment $attachment */ $attachment = Attachment::visible()->findOrFail($id); - $this->checkOwnablePermission('attachment-delete', $attachment); + $this->checkOwnablePermission(Permission::AttachmentDelete, $attachment); $this->attachmentService->deleteFile($attachment); diff --git a/app/Uploads/Controllers/AttachmentController.php b/app/Uploads/Controllers/AttachmentController.php index 809cdfa58..0886193e4 100644 --- a/app/Uploads/Controllers/AttachmentController.php +++ b/app/Uploads/Controllers/AttachmentController.php @@ -7,6 +7,7 @@ use BookStack\Entities\Repos\PageRepo; use BookStack\Exceptions\FileUploadException; use BookStack\Exceptions\NotFoundException; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Uploads\Attachment; use BookStack\Uploads\AttachmentService; use Exception; @@ -40,8 +41,8 @@ class AttachmentController extends Controller $pageId = $request->get('uploaded_to'); $page = $this->pageQueries->findVisibleByIdOrFail($pageId); - $this->checkPermission('attachment-create-all'); - $this->checkOwnablePermission('page-update', $page); + $this->checkPermission(Permission::AttachmentCreateAll); + $this->checkOwnablePermission(Permission::PageUpdate, $page); $uploadedFile = $request->file('file'); @@ -67,9 +68,9 @@ class AttachmentController extends Controller /** @var Attachment $attachment */ $attachment = Attachment::query()->findOrFail($attachmentId); - $this->checkOwnablePermission('view', $attachment->page); - $this->checkOwnablePermission('page-update', $attachment->page); - $this->checkOwnablePermission('attachment-create', $attachment); + $this->checkOwnablePermission(Permission::PageView, $attachment->page); + $this->checkOwnablePermission(Permission::PageUpdate, $attachment->page); + $this->checkOwnablePermission(Permission::AttachmentUpdate, $attachment); $uploadedFile = $request->file('file'); @@ -90,8 +91,8 @@ class AttachmentController extends Controller /** @var Attachment $attachment */ $attachment = Attachment::query()->findOrFail($attachmentId); - $this->checkOwnablePermission('page-update', $attachment->page); - $this->checkOwnablePermission('attachment-create', $attachment); + $this->checkOwnablePermission(Permission::PageUpdate, $attachment->page); + $this->checkOwnablePermission(Permission::AttachmentCreate, $attachment); return view('attachments.manager-edit-form', [ 'attachment' => $attachment, @@ -118,9 +119,9 @@ class AttachmentController extends Controller ]), 422); } - $this->checkOwnablePermission('page-view', $attachment->page); - $this->checkOwnablePermission('page-update', $attachment->page); - $this->checkOwnablePermission('attachment-update', $attachment); + $this->checkOwnablePermission(Permission::PageView, $attachment->page); + $this->checkOwnablePermission(Permission::PageUpdate, $attachment->page); + $this->checkOwnablePermission(Permission::AttachmentUpdate, $attachment); $attachment = $this->attachmentService->updateFile($attachment, [ 'name' => $request->get('attachment_edit_name'), @@ -156,8 +157,8 @@ class AttachmentController extends Controller $page = $this->pageQueries->findVisibleByIdOrFail($pageId); - $this->checkPermission('attachment-create-all'); - $this->checkOwnablePermission('page-update', $page); + $this->checkPermission(Permission::AttachmentCreateAll); + $this->checkOwnablePermission(Permission::PageUpdate, $page); $attachmentName = $request->get('attachment_link_name'); $link = $request->get('attachment_link_url'); @@ -176,7 +177,6 @@ class AttachmentController extends Controller public function listForPage(int $pageId) { $page = $this->pageQueries->findVisibleByIdOrFail($pageId); - $this->checkOwnablePermission('page-view', $page); return view('attachments.manager-list', [ 'attachments' => $page->attachments->all(), @@ -195,7 +195,7 @@ class AttachmentController extends Controller 'order' => ['required', 'array'], ]); $page = $this->pageQueries->findVisibleByIdOrFail($pageId); - $this->checkOwnablePermission('page-update', $page); + $this->checkOwnablePermission(Permission::PageUpdate, $page); $attachmentOrder = $request->get('order'); $this->attachmentService->updateFileOrderWithinPage($attachmentOrder, $pageId); @@ -220,7 +220,7 @@ class AttachmentController extends Controller throw new NotFoundException(trans('errors.attachment_not_found')); } - $this->checkOwnablePermission('page-view', $page); + $this->checkOwnablePermission(Permission::PageView, $page); if ($attachment->external) { return redirect($attachment->path); @@ -246,7 +246,7 @@ class AttachmentController extends Controller { /** @var Attachment $attachment */ $attachment = Attachment::query()->findOrFail($attachmentId); - $this->checkOwnablePermission('attachment-delete', $attachment); + $this->checkOwnablePermission(Permission::AttachmentDelete, $attachment); $this->attachmentService->deleteFile($attachment); return response()->json(['message' => trans('entities.attachments_deleted')]); diff --git a/app/Uploads/Controllers/DrawioImageController.php b/app/Uploads/Controllers/DrawioImageController.php index 6293da4f7..aff27b3b1 100644 --- a/app/Uploads/Controllers/DrawioImageController.php +++ b/app/Uploads/Controllers/DrawioImageController.php @@ -4,6 +4,7 @@ namespace BookStack\Uploads\Controllers; use BookStack\Exceptions\ImageUploadException; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Uploads\ImageRepo; use BookStack\Uploads\ImageResizer; use BookStack\Util\OutOfMemoryHandler; @@ -57,7 +58,7 @@ class DrawioImageController extends Controller 'uploaded_to' => ['required', 'integer'], ]); - $this->checkPermission('image-create-all'); + $this->checkPermission(Permission::ImageCreateAll); $imageBase64Data = $request->get('image'); try { diff --git a/app/Uploads/Controllers/GalleryImageController.php b/app/Uploads/Controllers/GalleryImageController.php index 1bc9da2d7..745efcde8 100644 --- a/app/Uploads/Controllers/GalleryImageController.php +++ b/app/Uploads/Controllers/GalleryImageController.php @@ -4,6 +4,7 @@ namespace BookStack\Uploads\Controllers; use BookStack\Exceptions\ImageUploadException; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Uploads\ImageRepo; use BookStack\Uploads\ImageResizer; use BookStack\Util\OutOfMemoryHandler; @@ -52,7 +53,7 @@ class GalleryImageController extends Controller */ public function create(Request $request) { - $this->checkPermission('image-create-all'); + $this->checkPermission(Permission::ImageCreateAll); try { $this->validate($request, [ diff --git a/app/Uploads/Controllers/ImageController.php b/app/Uploads/Controllers/ImageController.php index c68ffdf6b..da67639c1 100644 --- a/app/Uploads/Controllers/ImageController.php +++ b/app/Uploads/Controllers/ImageController.php @@ -6,6 +6,7 @@ use BookStack\Exceptions\ImageUploadException; use BookStack\Exceptions\NotFoundException; use BookStack\Exceptions\NotifyException; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Uploads\Image; use BookStack\Uploads\ImageRepo; use BookStack\Uploads\ImageResizer; @@ -50,7 +51,7 @@ class ImageController extends Controller $image = $this->imageRepo->getById($id); $this->checkImagePermission($image); - $this->checkOwnablePermission('image-update', $image); + $this->checkOwnablePermission(Permission::ImageUpdate, $image); $image = $this->imageRepo->updateImageDetails($image, $data); @@ -71,7 +72,7 @@ class ImageController extends Controller $image = $this->imageRepo->getById($id); $this->checkImagePermission($image); - $this->checkOwnablePermission('image-update', $image); + $this->checkOwnablePermission(Permission::ImageUpdate, $image); $file = $request->file('file'); new OutOfMemoryHandler(function () { @@ -125,7 +126,7 @@ class ImageController extends Controller public function destroy(string $id) { $image = $this->imageRepo->getById($id); - $this->checkOwnablePermission('image-delete', $image); + $this->checkOwnablePermission(Permission::ImageDelete, $image); $this->checkImagePermission($image); $this->imageRepo->destroyImage($image); @@ -140,7 +141,7 @@ class ImageController extends Controller { $image = $this->imageRepo->getById($id); $this->checkImagePermission($image); - $this->checkOwnablePermission('image-update', $image); + $this->checkOwnablePermission(Permission::ImageUpdate, $image); new OutOfMemoryHandler(function () { return $this->jsonError(trans('errors.image_thumbnail_memory_limit')); @@ -163,7 +164,7 @@ class ImageController extends Controller $relatedPage = $image->getPage(); if ($relatedPage) { - $this->checkOwnablePermission('page-view', $relatedPage); + $this->checkOwnablePermission(Permission::PageView, $relatedPage); } } } diff --git a/app/Uploads/Controllers/ImageGalleryApiController.php b/app/Uploads/Controllers/ImageGalleryApiController.php index d2a750c45..59696dc9a 100644 --- a/app/Uploads/Controllers/ImageGalleryApiController.php +++ b/app/Uploads/Controllers/ImageGalleryApiController.php @@ -4,6 +4,7 @@ namespace BookStack\Uploads\Controllers; use BookStack\Entities\Queries\PageQueries; use BookStack\Http\ApiController; +use BookStack\Permissions\Permission; use BookStack\Uploads\Image; use BookStack\Uploads\ImageRepo; use BookStack\Uploads\ImageResizer; @@ -65,7 +66,7 @@ class ImageGalleryApiController extends ApiController */ public function create(Request $request) { - $this->checkPermission('image-create-all'); + $this->checkPermission(Permission::ImageCreateAll); $data = $this->validate($request, $this->rules()['create']); $page = $this->pageQueries->findVisibleByIdOrFail($data['uploaded_to']); @@ -102,8 +103,8 @@ class ImageGalleryApiController extends ApiController { $data = $this->validate($request, $this->rules()['update']); $image = $this->imageRepo->getById($id); - $this->checkOwnablePermission('page-view', $image->getPage()); - $this->checkOwnablePermission('image-update', $image); + $this->checkOwnablePermission(Permission::PageView, $image->getPage()); + $this->checkOwnablePermission(Permission::ImageUpdate, $image); $this->imageRepo->updateImageDetails($image, $data); if (isset($data['image'])) { @@ -121,8 +122,8 @@ class ImageGalleryApiController extends ApiController public function delete(string $id) { $image = $this->imageRepo->getById($id); - $this->checkOwnablePermission('page-view', $image->getPage()); - $this->checkOwnablePermission('image-delete', $image); + $this->checkOwnablePermission(Permission::PageView, $image->getPage()); + $this->checkOwnablePermission(Permission::ImageDelete, $image); $this->imageRepo->destroyImage($image); return response('', 204); diff --git a/app/Users/Controllers/RoleApiController.php b/app/Users/Controllers/RoleApiController.php index 6d87c9e27..93ecc549b 100644 --- a/app/Users/Controllers/RoleApiController.php +++ b/app/Users/Controllers/RoleApiController.php @@ -3,6 +3,7 @@ namespace BookStack\Users\Controllers; use BookStack\Http\ApiController; +use BookStack\Permissions\Permission; use BookStack\Permissions\PermissionsRepo; use BookStack\Users\Models\Role; use Illuminate\Http\Request; @@ -38,7 +39,7 @@ class RoleApiController extends ApiController ) { // Checks for all endpoints in this controller $this->middleware(function ($request, $next) { - $this->checkPermission('user-roles-manage'); + $this->checkPermission(Permission::UserRolesManage); return $next($request); }); diff --git a/app/Users/Controllers/RoleController.php b/app/Users/Controllers/RoleController.php index 0a7fdcc9b..549f6e0ac 100644 --- a/app/Users/Controllers/RoleController.php +++ b/app/Users/Controllers/RoleController.php @@ -4,6 +4,7 @@ namespace BookStack\Users\Controllers; use BookStack\Exceptions\PermissionsException; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Permissions\PermissionsRepo; use BookStack\Users\Models\Role; use BookStack\Users\Queries\RolesAllPaginatedAndSorted; @@ -23,7 +24,7 @@ class RoleController extends Controller */ public function index(Request $request) { - $this->checkPermission('user-roles-manage'); + $this->checkPermission(Permission::UserRolesManage); $listOptions = SimpleListOptions::fromRequest($request, 'roles')->withSortOptions([ 'display_name' => trans('common.sort_name'), @@ -49,7 +50,7 @@ class RoleController extends Controller */ public function create(Request $request) { - $this->checkPermission('user-roles-manage'); + $this->checkPermission(Permission::UserRolesManage); /** @var ?Role $role */ $role = null; @@ -71,7 +72,7 @@ class RoleController extends Controller */ public function store(Request $request) { - $this->checkPermission('user-roles-manage'); + $this->checkPermission(Permission::UserRolesManage); $data = $this->validate($request, [ 'display_name' => ['required', 'min:3', 'max:180'], 'description' => ['max:180'], @@ -92,7 +93,7 @@ class RoleController extends Controller */ public function edit(string $id) { - $this->checkPermission('user-roles-manage'); + $this->checkPermission(Permission::UserRolesManage); $role = $this->permissionsRepo->getRoleById($id); $this->setPageTitle(trans('settings.role_edit')); @@ -105,7 +106,7 @@ class RoleController extends Controller */ public function update(Request $request, string $id) { - $this->checkPermission('user-roles-manage'); + $this->checkPermission(Permission::UserRolesManage); $data = $this->validate($request, [ 'display_name' => ['required', 'min:3', 'max:180'], 'description' => ['max:180'], @@ -127,7 +128,7 @@ class RoleController extends Controller */ public function showDelete(string $id) { - $this->checkPermission('user-roles-manage'); + $this->checkPermission(Permission::UserRolesManage); $role = $this->permissionsRepo->getRoleById($id); $roles = $this->permissionsRepo->getAllRolesExcept($role); $blankRole = $role->newInstance(['display_name' => trans('settings.role_delete_no_migration')]); @@ -146,7 +147,7 @@ class RoleController extends Controller */ public function delete(Request $request, string $id) { - $this->checkPermission('user-roles-manage'); + $this->checkPermission(Permission::UserRolesManage); try { $migrateRoleId = intval($request->get('migrate_role_id') ?: "0"); diff --git a/app/Users/Controllers/UserAccountController.php b/app/Users/Controllers/UserAccountController.php index 708a91e9d..54ca69c5d 100644 --- a/app/Users/Controllers/UserAccountController.php +++ b/app/Users/Controllers/UserAccountController.php @@ -4,6 +4,7 @@ namespace BookStack\Users\Controllers; use BookStack\Access\SocialDriverManager; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Permissions\PermissionApplicator; use BookStack\Settings\UserNotificationPreferences; use BookStack\Settings\UserShortcutMap; @@ -122,7 +123,7 @@ class UserAccountController extends Controller */ public function showNotifications(PermissionApplicator $permissions) { - $this->checkPermission('receive-notifications'); + $this->checkPermission(Permission::ReceiveNotifications); $preferences = (new UserNotificationPreferences(user())); @@ -145,7 +146,7 @@ class UserAccountController extends Controller public function updateNotifications(Request $request) { $this->preventAccessInDemoMode(); - $this->checkPermission('receive-notifications'); + $this->checkPermission(Permission::ReceiveNotifications); $data = $this->validate($request, [ 'preferences' => ['required', 'array'], 'preferences.*' => ['required', 'string'], diff --git a/app/Users/Controllers/UserApiController.php b/app/Users/Controllers/UserApiController.php index 351893b03..1efc82500 100644 --- a/app/Users/Controllers/UserApiController.php +++ b/app/Users/Controllers/UserApiController.php @@ -4,9 +4,9 @@ namespace BookStack\Users\Controllers; use BookStack\Exceptions\UserUpdateException; use BookStack\Http\ApiController; +use BookStack\Permissions\Permission; use BookStack\Users\Models\User; use BookStack\Users\UserRepo; -use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Validation\Rules\Password; @@ -26,7 +26,7 @@ class UserApiController extends ApiController // Checks for all endpoints in this controller $this->middleware(function ($request, $next) { - $this->checkPermission('users-manage'); + $this->checkPermission(Permission::UsersManage); $this->preventAccessInDemoMode(); return $next($request); diff --git a/app/Users/Controllers/UserController.php b/app/Users/Controllers/UserController.php index c6e4326e9..494221b14 100644 --- a/app/Users/Controllers/UserController.php +++ b/app/Users/Controllers/UserController.php @@ -7,6 +7,7 @@ use BookStack\Access\UserInviteException; use BookStack\Exceptions\ImageUploadException; use BookStack\Exceptions\UserUpdateException; use BookStack\Http\Controller; +use BookStack\Permissions\Permission; use BookStack\Uploads\ImageRepo; use BookStack\Users\Models\Role; use BookStack\Users\Queries\UsersAllPaginatedAndSorted; @@ -32,7 +33,7 @@ class UserController extends Controller */ public function index(Request $request) { - $this->checkPermission('users-manage'); + $this->checkPermission(Permission::UsersManage); $listOptions = SimpleListOptions::fromRequest($request, 'users')->withSortOptions([ 'name' => trans('common.sort_name'), @@ -58,7 +59,7 @@ class UserController extends Controller */ public function create() { - $this->checkPermission('users-manage'); + $this->checkPermission(Permission::UsersManage); $authMethod = config('auth.method'); $roles = Role::query()->orderBy('display_name', 'asc')->get(); $this->setPageTitle(trans('settings.users_add_new')); @@ -73,7 +74,7 @@ class UserController extends Controller */ public function store(Request $request) { - $this->checkPermission('users-manage'); + $this->checkPermission(Permission::UsersManage); $authMethod = config('auth.method'); $sendInvite = ($request->get('send_invite', 'false') === 'true'); @@ -111,7 +112,7 @@ class UserController extends Controller */ public function edit(int $id, SocialDriverManager $socialDriverManager) { - $this->checkPermission('users-manage'); + $this->checkPermission(Permission::UsersManage); $user = $this->userRepo->getById($id); $user->load(['apiTokens', 'mfaValues']); @@ -141,7 +142,7 @@ class UserController extends Controller public function update(Request $request, int $id) { $this->preventAccessInDemoMode(); - $this->checkPermission('users-manage'); + $this->checkPermission(Permission::UsersManage); $validated = $this->validate($request, [ 'name' => ['min:1', 'max:100'], @@ -182,7 +183,7 @@ class UserController extends Controller */ public function delete(int $id) { - $this->checkPermission('users-manage'); + $this->checkPermission(Permission::UsersManage); $user = $this->userRepo->getById($id); $this->setPageTitle(trans('settings.users_delete_named', ['userName' => $user->name])); @@ -198,7 +199,7 @@ class UserController extends Controller public function destroy(Request $request, int $id) { $this->preventAccessInDemoMode(); - $this->checkPermission('users-manage'); + $this->checkPermission(Permission::UsersManage); $user = $this->userRepo->getById($id); $newOwnerId = intval($request->get('new_owner_id')) ?: null; diff --git a/resources/views/home/books.blade.php b/resources/views/home/books.blade.php index a2f2bf796..e0d2aeb1c 100644 --- a/resources/views/home/books.blade.php +++ b/resources/views/home/books.blade.php @@ -12,7 +12,7 @@
{{ trans('common.actions') }}