| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Tests\Helpers; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | use BookStack\Entities\Models\Entity; | 
					
						
							| 
									
										
										
										
											2023-05-18 00:56:55 +08:00
										 |  |  | use BookStack\Permissions\Models\EntityPermission; | 
					
						
							|  |  |  | use BookStack\Permissions\Models\RolePermission; | 
					
						
							|  |  |  | use BookStack\Users\Models\Role; | 
					
						
							|  |  |  | use BookStack\Users\Models\User; | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class PermissionsProvider | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     protected UserRoleProvider $userRoleProvider; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     public function __construct(UserRoleProvider $userRoleProvider) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->userRoleProvider = $userRoleProvider; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Grant role permissions to the provided user. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function grantUserRolePermissions(User $user, array $permissions): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $newRole = $this->userRoleProvider->createRole($permissions); | 
					
						
							|  |  |  |         $user->attachRole($newRole); | 
					
						
							|  |  |  |         $user->load('roles'); | 
					
						
							|  |  |  |         $user->clearPermissionCache(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Completely remove specific role permissions from the provided user. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function removeUserRolePermissions(User $user, array $permissions): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         foreach ($permissions as $permissionName) { | 
					
						
							|  |  |  |             /** @var RolePermission $permission */ | 
					
						
							|  |  |  |             $permission = RolePermission::query() | 
					
						
							|  |  |  |                 ->where('name', '=', $permissionName) | 
					
						
							|  |  |  |                 ->firstOrFail(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $roles = $user->roles()->whereHas('permissions', function ($query) use ($permission) { | 
					
						
							|  |  |  |                 $query->where('id', '=', $permission->id); | 
					
						
							|  |  |  |             })->get(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /** @var Role $role */ | 
					
						
							|  |  |  |             foreach ($roles as $role) { | 
					
						
							|  |  |  |                 $role->detachPermission($permission); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $user->clearPermissionCache(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Change the owner of the given entity to the given user. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function changeEntityOwner(Entity $entity, User $newOwner): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $entity->owned_by = $newOwner->id; | 
					
						
							|  |  |  |         $entity->save(); | 
					
						
							|  |  |  |         $entity->rebuildPermissions(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Regenerate the permission for an entity. | 
					
						
							|  |  |  |      * Centralised to manage clearing of cached elements between requests. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function regenerateForEntity(Entity $entity): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $entity->rebuildPermissions(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Set the given entity as having restricted permissions, and apply the given | 
					
						
							|  |  |  |      * permissions for the given roles. | 
					
						
							|  |  |  |      * @param string[] $actions | 
					
						
							|  |  |  |      * @param Role[] $roles | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function setEntityPermissions(Entity $entity, array $actions = [], array $roles = [], $inherit = false): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $entity->permissions()->delete(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $permissions = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!$inherit) { | 
					
						
							|  |  |  |             // Set default permissions to not allow actions so that only the provided role permissions are at play.
 | 
					
						
							| 
									
										
										
										
											2023-01-21 21:03:47 +08:00
										 |  |  |             $permissions[] = ['role_id' => 0, 'view' => false, 'create' => false, 'update' => false, 'delete' => false]; | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach ($roles as $role) { | 
					
						
							|  |  |  |             $permissions[] = $this->actionListToEntityPermissionData($actions, $role->id); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->addEntityPermissionEntries($entity, $permissions); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-21 21:03:47 +08:00
										 |  |  |     public function addEntityPermission(Entity $entity, array $actionList, Role $role) | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-01-21 21:03:47 +08:00
										 |  |  |         $permissionData = $this->actionListToEntityPermissionData($actionList, $role->id); | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |         $this->addEntityPermissionEntries($entity, [$permissionData]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-25 04:42:20 +08:00
										 |  |  |     public function setFallbackPermissions(Entity $entity, array $actionList) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $entity->permissions()->where('role_id', '=', 0)->delete(); | 
					
						
							|  |  |  |         $permissionData = $this->actionListToEntityPermissionData($actionList, 0); | 
					
						
							|  |  |  |         $this->addEntityPermissionEntries($entity, [$permissionData]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Disable inherited permissions on the given entity. | 
					
						
							|  |  |  |      * Effectively sets the "Other Users" UI permission option to not inherit, with no permissions. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function disableEntityInheritedPermissions(Entity $entity): void | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-01-21 21:03:47 +08:00
										 |  |  |         $entity->permissions()->where('role_id', '=', 0)->delete(); | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |         $fallback = $this->actionListToEntityPermissionData([]); | 
					
						
							|  |  |  |         $this->addEntityPermissionEntries($entity, [$fallback]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     protected function addEntityPermissionEntries(Entity $entity, array $entityPermissionData): void | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $entity->permissions()->createMany($entityPermissionData); | 
					
						
							|  |  |  |         $entity->load('permissions'); | 
					
						
							|  |  |  |         $this->regenerateForEntity($entity); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * For the given simple array of string actions (view, create, update, delete), convert | 
					
						
							|  |  |  |      * the format to entity permission data, where permission is granted if the action is in the | 
					
						
							|  |  |  |      * given actionList array. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-01-21 21:03:47 +08:00
										 |  |  |     protected function actionListToEntityPermissionData(array $actionList, int $roleId = 0): array | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-01-21 21:03:47 +08:00
										 |  |  |         $permissionData = ['role_id' => $roleId]; | 
					
						
							| 
									
										
										
										
											2023-01-21 19:08:34 +08:00
										 |  |  |         foreach (EntityPermission::PERMISSIONS as $possibleAction) { | 
					
						
							|  |  |  |             $permissionData[$possibleAction] = in_array($possibleAction, $actionList); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $permissionData; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |