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