mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-07-02 22:44:33 +02:00
Added various useful presets for permissions
This commit is contained in:
parent
5829d42968
commit
1de88e0494
13 changed files with 369 additions and 231 deletions
|
@ -51,6 +51,7 @@ use App\Form\AdminPages\GroupAdminForm;
|
|||
use App\Services\EntityExporter;
|
||||
use App\Services\EntityImporter;
|
||||
use App\Services\StructuralElementRecursionHelper;
|
||||
use App\Services\UserSystem\PermissionPresetsHelper;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
@ -73,8 +74,27 @@ class GroupController extends BaseAdminController
|
|||
* @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="group_edit")
|
||||
* @Route("/{id}/", requirements={"id"="\d+"})
|
||||
*/
|
||||
public function edit(Group $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
public function edit(Group $entity, Request $request, EntityManagerInterface $em, PermissionPresetsHelper $permissionPresetsHelper, ?string $timestamp = null): Response
|
||||
{
|
||||
//Handle permissions presets
|
||||
if ($request->request->has('permission_preset')) {
|
||||
$this->denyAccessUnlessGranted('edit_permissions', $entity);
|
||||
if ($this->isCsrfTokenValid('group'.$entity->getId(), $request->request->get('_token'))) {
|
||||
$preset = $request->request->get('permission_preset');
|
||||
|
||||
$permissionPresetsHelper->applyPreset($entity, $preset);
|
||||
|
||||
$em->flush();
|
||||
|
||||
$this->addFlash('success', 'user.edit.permission_success');
|
||||
|
||||
//We need to stop the execution here, or our permissions changes will be overwritten by the form values
|
||||
return $this->redirectToRoute('group_edit', ['id' => $entity->getID()]);
|
||||
} else {
|
||||
$this->addFlash('danger', 'csfr_invalid');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_edit($entity, $request, $em, $timestamp);
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ use App\Form\UserAdminForm;
|
|||
use App\Services\EntityExporter;
|
||||
use App\Services\EntityImporter;
|
||||
use App\Services\StructuralElementRecursionHelper;
|
||||
use App\Services\UserSystem\PermissionPresetsHelper;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
|
@ -101,7 +102,7 @@ class UserController extends AdminPages\BaseAdminController
|
|||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function edit(User $entity, Request $request, EntityManagerInterface $em, ?string $timestamp = null): Response
|
||||
public function edit(User $entity, Request $request, EntityManagerInterface $em, PermissionPresetsHelper $permissionPresetsHelper, ?string $timestamp = null): Response
|
||||
{
|
||||
//Handle 2FA disabling
|
||||
|
||||
|
@ -132,6 +133,25 @@ class UserController extends AdminPages\BaseAdminController
|
|||
}
|
||||
}
|
||||
|
||||
//Handle permissions presets
|
||||
if ($request->request->has('permission_preset')) {
|
||||
$this->denyAccessUnlessGranted('edit_permissions', $entity);
|
||||
if ($this->isCsrfTokenValid('reset_2fa'.$entity->getId(), $request->request->get('_token'))) {
|
||||
$preset = $request->request->get('permission_preset');
|
||||
|
||||
$permissionPresetsHelper->applyPreset($entity, $preset);
|
||||
|
||||
$em->flush();
|
||||
|
||||
$this->addFlash('success', 'user.edit.permission_success');
|
||||
|
||||
//We need to stop the execution here, or our permissions changes will be overwritten by the form values
|
||||
return $this->redirectToRoute('user_edit', ['id' => $entity->getID()]);
|
||||
} else {
|
||||
$this->addFlash('danger', 'csfr_invalid');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_edit($entity, $request, $em, $timestamp);
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,16 @@ final class PermissionData implements \JsonSerializable
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the saved permissions and set all operations to inherit (which means they are not defined).
|
||||
* @return $this
|
||||
*/
|
||||
public function resetPermissions(): self
|
||||
{
|
||||
$this->data = [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Permission Data Instance using the given JSON encoded data
|
||||
* @param string $json
|
||||
|
|
|
@ -64,6 +64,7 @@ class GroupAdminForm extends BaseEntityAdminForm
|
|||
'mapped' => false,
|
||||
'data' => $builder->getData(),
|
||||
'disabled' => !$this->security->isGranted('edit_permissions', $entity),
|
||||
'show_presets' => $this->security->isGranted('edit_permissions', $entity) && !$is_new,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ class PermissionsType extends AbstractType
|
|||
{
|
||||
$resolver->setDefaults([
|
||||
'show_legend' => true,
|
||||
'show_presets' => false,
|
||||
'constraints' => static function (Options $options) {
|
||||
if (!$options['disabled']) {
|
||||
return [new NoLockout()];
|
||||
|
@ -80,6 +81,7 @@ class PermissionsType extends AbstractType
|
|||
public function buildView(FormView $view, FormInterface $form, array $options): void
|
||||
{
|
||||
$view->vars['show_legend'] = $options['show_legend'];
|
||||
$view->vars['show_presets'] = $options['show_presets'];
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
|
|
|
@ -227,6 +227,7 @@ class UserAdminForm extends AbstractType
|
|||
'mapped' => false,
|
||||
'data' => $builder->getData(),
|
||||
'disabled' => !$this->security->isGranted('edit_permissions', $entity),
|
||||
'show_presets' => $this->security->isGranted('edit_permissions', $entity) && !$is_new,
|
||||
])
|
||||
;
|
||||
/*->add('comment', CKEditorType::class, ['required' => false,
|
||||
|
|
|
@ -206,7 +206,7 @@ class PermissionResolver
|
|||
|
||||
/**
|
||||
* This functions sets all operations mentioned in the alsoSet value of a permission, so that the structure is always valid.
|
||||
* @param User $user
|
||||
* @param HasPermissionsInterface $user
|
||||
* @return void
|
||||
*/
|
||||
public function ensureCorrectSetOperations(HasPermissionsInterface $user): void
|
||||
|
@ -261,6 +261,26 @@ class PermissionResolver
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all operations of the given permissions to the given value.
|
||||
* Please note that you have to call ensureCorrectSetOperations() after this function, to ensure that all alsoSet values are set.
|
||||
*
|
||||
* @param HasPermissionsInterface $perm_holder
|
||||
* @param string $permission
|
||||
* @param bool|null $new_value
|
||||
* @return void
|
||||
*/
|
||||
public function setAllOperationsOfPermission(HasPermissionsInterface $perm_holder, string $permission, ?bool $new_value): void
|
||||
{
|
||||
if (!$this->isValidPermission($permission)) {
|
||||
throw new InvalidArgumentException(sprintf('A permission with that name is not existing! Got %s.', $permission));
|
||||
}
|
||||
|
||||
foreach ($this->permission_structure['perms'][$permission]['operations'] as $op_key => $op) {
|
||||
$this->setPermission($perm_holder, $permission, $op_key, $new_value);
|
||||
}
|
||||
}
|
||||
|
||||
protected function generatePermissionStructure()
|
||||
{
|
||||
$cache = new ConfigCache($this->cache_file, $this->is_debug);
|
||||
|
|
143
src/Services/UserSystem/PermissionPresetsHelper.php
Normal file
143
src/Services/UserSystem/PermissionPresetsHelper.php
Normal file
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services\UserSystem;
|
||||
|
||||
use App\Entity\UserSystem\PermissionData;
|
||||
use App\Entity\UserSystem\User;
|
||||
use App\Security\Interfaces\HasPermissionsInterface;
|
||||
use App\Services\PermissionResolver;
|
||||
|
||||
class PermissionPresetsHelper
|
||||
{
|
||||
private PermissionResolver $permissionResolver;
|
||||
|
||||
public function __construct(PermissionResolver $permissionResolver)
|
||||
{
|
||||
$this->permissionResolver = $permissionResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the given preset to the permission holding entity (like a user)
|
||||
* The permission data will be reset during the process and then the preset will be applied.
|
||||
*
|
||||
* @param
|
||||
* @param string $preset_name The name of the preset to use
|
||||
* @return PermissionData
|
||||
*/
|
||||
public function applyPreset(HasPermissionsInterface $perm_holder, string $preset_name): HasPermissionsInterface
|
||||
{
|
||||
//We need to reset the permission data first (afterwards all values are inherit)
|
||||
$perm_holder->getPermissions()->resetPermissions();
|
||||
|
||||
switch($preset_name) {
|
||||
case 'all_inherit':
|
||||
//Do nothing, all values are inherit after reset
|
||||
break;
|
||||
case 'all_forbid':
|
||||
$this->allForbid($perm_holder);
|
||||
break;
|
||||
case 'all_allow':
|
||||
$this->allAllow($perm_holder);
|
||||
break;
|
||||
case 'read_only':
|
||||
$this->readOnly($perm_holder);
|
||||
break;
|
||||
case 'editor':
|
||||
$this->editor($perm_holder);
|
||||
break;
|
||||
case 'admin':
|
||||
$this->admin($perm_holder);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException('Unknown permission preset name: '.$preset_name);
|
||||
}
|
||||
|
||||
//Ensure that permissions are valid (alsoSet values are set), this allows us to use the permission inheritance system to keep the presets short
|
||||
$this->permissionResolver->ensureCorrectSetOperations($perm_holder);
|
||||
|
||||
return $perm_holder;
|
||||
}
|
||||
|
||||
private function admin(HasPermissionsInterface $perm_holder): void
|
||||
{
|
||||
//Apply everything from editor permission
|
||||
$this->editor($perm_holder);
|
||||
|
||||
//Allow user and group access
|
||||
$this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'users', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'groups', PermissionData::ALLOW);
|
||||
|
||||
//Allow access to system log and server infos
|
||||
$this->permissionResolver->setPermission($perm_holder, 'system', 'show_logs', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setPermission($perm_holder, 'system', 'server_infos', PermissionData::ALLOW);
|
||||
}
|
||||
|
||||
private function editor(HasPermissionsInterface $permHolder): HasPermissionsInterface
|
||||
{
|
||||
//Apply everything from read-only
|
||||
$this->readOnly($permHolder);
|
||||
|
||||
//Set datastructures
|
||||
$this->permissionResolver->setAllOperationsOfPermission($permHolder, 'parts', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setAllOperationsOfPermission($permHolder, 'categories', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setAllOperationsOfPermission($permHolder, 'storelocations', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setAllOperationsOfPermission($permHolder, 'footprints', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setAllOperationsOfPermission($permHolder, 'manufacturers', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setAllOperationsOfPermission($permHolder, 'attachment_types', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setAllOperationsOfPermission($permHolder, 'currencies', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setAllOperationsOfPermission($permHolder, 'measurement_units', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setAllOperationsOfPermission($permHolder, 'suppliers', PermissionData::ALLOW);
|
||||
|
||||
//Attachments permissions
|
||||
$this->permissionResolver->setPermission($permHolder, 'attachments', 'show_private', PermissionData::ALLOW);
|
||||
|
||||
//Labels permissions (allow all except use twig)
|
||||
$this->permissionResolver->setAllOperationsOfPermission($permHolder, 'labels', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setPermission($permHolder,'labels', 'use_twig', PermissionData::INHERIT);
|
||||
|
||||
//Self permissions
|
||||
$this->permissionResolver->setPermission($permHolder, 'self', 'edit_infos', PermissionData::ALLOW);
|
||||
|
||||
//Various other permissions
|
||||
$this->permissionResolver->setPermission($permHolder, 'tools', 'lastActivity', PermissionData::ALLOW);
|
||||
|
||||
|
||||
return $permHolder;
|
||||
}
|
||||
|
||||
private function readOnly(HasPermissionsInterface $perm_holder): HasPermissionsInterface
|
||||
{
|
||||
//It is sufficient to only set the read operation to allow, read operations for datastructures are inherited
|
||||
$this->permissionResolver->setPermission($perm_holder, 'parts', 'read', PermissionData::ALLOW);
|
||||
|
||||
//Set tools permissions
|
||||
$this->permissionResolver->setPermission($perm_holder, 'tools', 'statistics', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setPermission($perm_holder, 'tools', 'label_scanner', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setPermission($perm_holder, 'tools', 'reel_calculator', PermissionData::ALLOW);
|
||||
|
||||
//Set attachments permissions
|
||||
$this->permissionResolver->setPermission($perm_holder, 'attachments', 'list_attachments', PermissionData::ALLOW);
|
||||
|
||||
//Set user (self) permissions
|
||||
$this->permissionResolver->setPermission($perm_holder, 'self', 'show_permissions', PermissionData::ALLOW);
|
||||
|
||||
//Label permissions
|
||||
$this->permissionResolver->setPermission($perm_holder, 'labels', 'create_labels', PermissionData::ALLOW);
|
||||
$this->permissionResolver->setPermission($perm_holder, 'labels', 'edit_options', PermissionData::ALLOW);
|
||||
|
||||
return $perm_holder;
|
||||
}
|
||||
|
||||
private function AllForbid(HasPermissionsInterface $perm_holder): HasPermissionsInterface
|
||||
{
|
||||
$this->permissionResolver->setAllPermissions($perm_holder, PermissionData::DISALLOW);
|
||||
return $perm_holder;
|
||||
}
|
||||
|
||||
private function AllAllow(HasPermissionsInterface $perm_holder): HasPermissionsInterface
|
||||
{
|
||||
$this->permissionResolver->setAllPermissions($perm_holder, PermissionData::ALLOW);
|
||||
return $perm_holder;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue