]> BookStack Code Mirror - bookstack/blob - tests/Helpers/PermissionsProvider.php
Fixed collapsed perm. gen for book sub-items.
[bookstack] / tests / Helpers / PermissionsProvider.php
1 <?php
2
3 namespace Tests\Helpers;
4
5 use BookStack\Auth\Permissions\EntityPermission;
6 use BookStack\Auth\Permissions\RolePermission;
7 use BookStack\Auth\Role;
8 use BookStack\Auth\User;
9 use BookStack\Entities\Models\Entity;
10
11 class PermissionsProvider
12 {
13     protected UserRoleProvider $userRoleProvider;
14
15     public function __construct(UserRoleProvider $userRoleProvider)
16     {
17         $this->userRoleProvider = $userRoleProvider;
18     }
19
20     /**
21      * Grant role permissions to the provided user.
22      */
23     public function grantUserRolePermissions(User $user, array $permissions): void
24     {
25         $newRole = $this->userRoleProvider->createRole($permissions);
26         $user->attachRole($newRole);
27         $user->load('roles');
28         $user->clearPermissionCache();
29     }
30
31     /**
32      * Completely remove specific role permissions from the provided user.
33      */
34     public function removeUserRolePermissions(User $user, array $permissions): void
35     {
36         foreach ($permissions as $permissionName) {
37             /** @var RolePermission $permission */
38             $permission = RolePermission::query()
39                 ->where('name', '=', $permissionName)
40                 ->firstOrFail();
41
42             $roles = $user->roles()->whereHas('permissions', function ($query) use ($permission) {
43                 $query->where('id', '=', $permission->id);
44             })->get();
45
46             /** @var Role $role */
47             foreach ($roles as $role) {
48                 $role->detachPermission($permission);
49             }
50
51             $user->clearPermissionCache();
52         }
53     }
54
55     /**
56      * Change the owner of the given entity to the given user.
57      */
58     public function changeEntityOwner(Entity $entity, User $newOwner): void
59     {
60         $entity->owned_by = $newOwner->id;
61         $entity->save();
62         $entity->rebuildPermissions();
63     }
64
65     /**
66      * Regenerate the permission for an entity.
67      * Centralised to manage clearing of cached elements between requests.
68      */
69     public function regenerateForEntity(Entity $entity): void
70     {
71         $entity->rebuildPermissions();
72     }
73
74     /**
75      * Set the given entity as having restricted permissions, and apply the given
76      * permissions for the given roles.
77      * @param string[] $actions
78      * @param Role[] $roles
79      */
80     public function setEntityPermissions(Entity $entity, array $actions = [], array $roles = [], $inherit = false): void
81     {
82         $entity->permissions()->delete();
83
84         $permissions = [];
85
86         if (!$inherit) {
87             // Set default permissions to not allow actions so that only the provided role permissions are at play.
88             $permissions[] = ['role_id' => null, 'user_id' => null, 'view' => false, 'create' => false, 'update' => false, 'delete' => false];
89         }
90
91         foreach ($roles as $role) {
92             $permissions[] = $this->actionListToEntityPermissionData($actions, $role->id);
93         }
94
95         $this->addEntityPermissionEntries($entity, $permissions);
96     }
97
98     public function addEntityPermission(Entity $entity, array $actionList, ?Role $role = null, ?User $user = null)
99     {
100         $permissionData = $this->actionListToEntityPermissionData($actionList, $role->id ?? null, $user->id ?? null);
101         $this->addEntityPermissionEntries($entity, [$permissionData]);
102     }
103
104     /**
105      * Disable inherited permissions on the given entity.
106      * Effectively sets the "Other Users" UI permission option to not inherit, with no permissions.
107      */
108     public function disableEntityInheritedPermissions(Entity $entity): void
109     {
110         $entity->permissions()->whereNull(['user_id', 'role_id'])->delete();
111         $fallback = $this->actionListToEntityPermissionData([]);
112         $this->addEntityPermissionEntries($entity, [$fallback]);
113     }
114
115     protected function addEntityPermissionEntries(Entity $entity, array $entityPermissionData): void
116     {
117         $entity->permissions()->createMany($entityPermissionData);
118         $entity->load('permissions');
119         $this->regenerateForEntity($entity);
120     }
121
122     /**
123      * For the given simple array of string actions (view, create, update, delete), convert
124      * the format to entity permission data, where permission is granted if the action is in the
125      * given actionList array.
126      */
127     protected function actionListToEntityPermissionData(array $actionList, int $roleId = null, int $userId = null): array
128     {
129         $permissionData = ['role_id' => $roleId, 'user_id' => $userId];
130         foreach (EntityPermission::PERMISSIONS as $possibleAction) {
131             $permissionData[$possibleAction] = in_array($possibleAction, $actionList);
132         }
133
134         return $permissionData;
135     }
136 }