X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/a6633642232efd164d4708967ab59e498fbff896..refs/pull/5280/head:/app/Entities/Tools/PermissionsUpdater.php diff --git a/app/Entities/Tools/PermissionsUpdater.php b/app/Entities/Tools/PermissionsUpdater.php index 8a27ce75b..9f3b8f952 100644 --- a/app/Entities/Tools/PermissionsUpdater.php +++ b/app/Entities/Tools/PermissionsUpdater.php @@ -1,25 +1,27 @@ -get('restricted') === 'true'; - $permissions = $request->get('restrictions', null); + $permissions = $request->get('permissions', null); $ownerId = $request->get('owned_by', null); - $entity->restricted = $restricted; $entity->permissions()->delete(); if (!is_null($permissions)) { @@ -34,7 +36,39 @@ class PermissionsUpdater $entity->save(); $entity->rebuildPermissions(); - Activity::addForEntity($entity, ActivityType::PERMISSIONS_UPDATE); + Activity::add(ActivityType::PERMISSIONS_UPDATE, $entity); + } + + /** + * Update permissions from API request data. + */ + public function updateFromApiRequestData(Entity $entity, array $data): void + { + if (isset($data['role_permissions'])) { + $entity->permissions()->where('role_id', '!=', 0)->delete(); + $rolePermissionData = $this->formatPermissionsFromApiRequestToEntityPermissions($data['role_permissions'] ?? [], false); + $entity->permissions()->createMany($rolePermissionData); + } + + if (array_key_exists('fallback_permissions', $data)) { + $entity->permissions()->where('role_id', '=', 0)->delete(); + } + + if (isset($data['fallback_permissions']['inheriting']) && $data['fallback_permissions']['inheriting'] !== true) { + $fallbackData = $data['fallback_permissions']; + $fallbackData['role_id'] = 0; + $rolePermissionData = $this->formatPermissionsFromApiRequestToEntityPermissions([$fallbackData], true); + $entity->permissions()->createMany($rolePermissionData); + } + + if (isset($data['owner_id'])) { + $this->updateOwnerFromId($entity, intval($data['owner_id'])); + } + + $entity->save(); + $entity->rebuildPermissions(); + + Activity::add(ActivityType::PERMISSIONS_UPDATE, $entity); } /** @@ -42,7 +76,7 @@ class PermissionsUpdater * Checks the user exists in the system first. * Does not save the model, just updates it. */ - protected function updateOwnerFromId(Entity $entity, int $newOwnerId) + protected function updateOwnerFromId(Entity $entity, int $newOwnerId): void { $newOwner = User::query()->find($newOwnerId); if (!is_null($newOwner)) { @@ -51,18 +85,77 @@ class PermissionsUpdater } /** - * Format permissions provided from a permission form to be - * EntityPermission data. + * Format permissions provided from a permission form to be EntityPermission data. + */ + protected function formatPermissionsFromRequestToEntityPermissions(array $permissions): array + { + $formatted = []; + + foreach ($permissions as $roleId => $info) { + $entityPermissionData = ['role_id' => $roleId]; + foreach (EntityPermission::PERMISSIONS as $permission) { + $entityPermissionData[$permission] = (($info[$permission] ?? false) === "true"); + } + $formatted[] = $entityPermissionData; + } + + return $this->filterEntityPermissionDataUponRole($formatted, true); + } + + protected function formatPermissionsFromApiRequestToEntityPermissions(array $permissions, bool $allowFallback): array + { + $formatted = []; + + foreach ($permissions as $requestPermissionData) { + $entityPermissionData = ['role_id' => $requestPermissionData['role_id']]; + foreach (EntityPermission::PERMISSIONS as $permission) { + $entityPermissionData[$permission] = boolval($requestPermissionData[$permission] ?? false); + } + $formatted[] = $entityPermissionData; + } + + return $this->filterEntityPermissionDataUponRole($formatted, $allowFallback); + } + + protected function filterEntityPermissionDataUponRole(array $entityPermissionData, bool $allowFallback): array + { + $roleIds = []; + foreach ($entityPermissionData as $permissionEntry) { + $roleIds[] = intval($permissionEntry['role_id']); + } + + $actualRoleIds = array_unique(array_values(array_filter($roleIds))); + $rolesById = Role::query()->whereIn('id', $actualRoleIds)->get('id')->keyBy('id'); + + return array_values(array_filter($entityPermissionData, function ($data) use ($rolesById, $allowFallback) { + if (intval($data['role_id']) === 0) { + return $allowFallback; + } + + return $rolesById->has($data['role_id']); + })); + } + + /** + * Copy down the permissions of the given shelf to all child books. */ - protected function formatPermissionsFromRequestToEntityPermissions(array $permissions): Collection + public function updateBookPermissionsFromShelf(Bookshelf $shelf, $checkUserPermissions = true): int { - return collect($permissions)->flatMap(function ($restrictions, $roleId) { - return collect($restrictions)->keys()->map(function ($action) use ($roleId) { - return [ - 'role_id' => $roleId, - 'action' => strtolower($action), - ] ; - }); - }); + $shelfPermissions = $shelf->permissions()->get(['role_id', 'view', 'create', 'update', 'delete'])->toArray(); + $shelfBooks = $shelf->books()->get(['id', 'owned_by']); + $updatedBookCount = 0; + + /** @var Book $book */ + foreach ($shelfBooks as $book) { + if ($checkUserPermissions && !userCan('restrictions-manage', $book)) { + continue; + } + $book->permissions()->delete(); + $book->permissions()->createMany($shelfPermissions); + $book->rebuildPermissions(); + $updatedBookCount++; + } + + return $updatedBookCount; } }