3 namespace Tests\Helpers;
5 use BookStack\Auth\Permissions\EntityPermission;
6 use BookStack\Auth\Permissions\JointPermissionBuilder;
7 use BookStack\Auth\Permissions\RolePermission;
8 use BookStack\Auth\Role;
9 use BookStack\Auth\User;
10 use BookStack\Entities\Models\Entity;
12 class PermissionsProvider
14 protected UserRoleProvider $userRoleProvider;
16 public function __construct(UserRoleProvider $userRoleProvider)
18 $this->userRoleProvider = $userRoleProvider;
22 * Grant role permissions to the provided user.
24 public function grantUserRolePermissions(User $user, array $permissions): void
26 $newRole = $this->userRoleProvider->createRole($permissions);
27 $user->attachRole($newRole);
29 $user->clearPermissionCache();
33 * Completely remove specific role permissions from the provided user.
35 public function removeUserRolePermissions(User $user, array $permissions): void
37 foreach ($permissions as $permissionName) {
38 /** @var RolePermission $permission */
39 $permission = RolePermission::query()
40 ->where('name', '=', $permissionName)
43 $roles = $user->roles()->whereHas('permissions', function ($query) use ($permission) {
44 $query->where('id', '=', $permission->id);
47 /** @var Role $role */
48 foreach ($roles as $role) {
49 $role->detachPermission($permission);
52 $user->clearPermissionCache();
57 * Change the owner of the given entity to the given user.
59 public function changeEntityOwner(Entity $entity, User $newOwner): void
61 $entity->owned_by = $newOwner->id;
63 $entity->rebuildPermissions();
67 * Regenerate the permission for an entity.
68 * Centralised to manage clearing of cached elements between requests.
70 public function regenerateForEntity(Entity $entity): void
72 $entity->rebuildPermissions();
73 $entity->load('jointPermissions');
77 * Set the given entity as having restricted permissions, and apply the given
78 * permissions for the given roles.
79 * @param string[] $actions
80 * @param Role[] $roles
82 public function setEntityPermissions(Entity $entity, array $actions = [], array $roles = [], $inherit = false): void
84 $entity->permissions()->delete();
89 // Set default permissions to not allow actions so that only the provided role permissions are at play.
90 $permissions[] = ['role_id' => null, 'user_id' => null, 'view' => false, 'create' => false, 'update' => false, 'delete' => false];
93 foreach ($roles as $role) {
94 $permissions[] = $this->actionListToEntityPermissionData($actions, $role->id);
97 $this->addEntityPermissionEntries($entity, $permissions);
100 public function addEntityPermission(Entity $entity, array $actionList, ?Role $role = null, ?User $user = null)
102 $permissionData = $this->actionListToEntityPermissionData($actionList, $role->id ?? null, $user->id ?? null);
103 $this->addEntityPermissionEntries($entity, [$permissionData]);
107 * Disable inherited permissions on the given entity.
108 * Effectively sets the "Other Users" UI permission option to not inherit, with no permissions.
110 public function disableEntityInheritedPermissions(Entity $entity): void
112 $entity->permissions()->whereNull(['user_id', 'role_id'])->delete();
113 $fallback = $this->actionListToEntityPermissionData([]);
114 $this->addEntityPermissionEntries($entity, [$fallback]);
117 protected function addEntityPermissionEntries(Entity $entity, array $entityPermissionData): void
119 $entity->permissions()->createMany($entityPermissionData);
120 $entity->load('permissions');
121 $this->regenerateForEntity($entity);
125 * For the given simple array of string actions (view, create, update, delete), convert
126 * the format to entity permission data, where permission is granted if the action is in the
127 * given actionList array.
129 protected function actionListToEntityPermissionData(array $actionList, int $roleId = null, int $userId = null): array
131 $permissionData = ['role_id' => $roleId, 'user_id' => $userId];
132 foreach (EntityPermission::PERMISSIONS as $possibleAction) {
133 $permissionData[$possibleAction] = in_array($possibleAction, $actionList);
136 return $permissionData;