mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 09:35:49 +02:00
Automatically upgrade permission version schema in the background when needed on a request.
This commit is contained in:
parent
0e56f11b6b
commit
7aa88a8dbd
6 changed files with 130 additions and 5 deletions
|
@ -27,7 +27,7 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co
|
||||||
'currencies.read', 'attachment_types.read', 'measurement_units.read']
|
'currencies.read', 'attachment_types.read', 'measurement_units.read']
|
||||||
edit:
|
edit:
|
||||||
label: "perm.edit"
|
label: "perm.edit"
|
||||||
alsoSet: ['read', 'parts_stock.withdraw', 'parts_stock.add', 'parts_stock.move']
|
alsoSet: ['read'] #['read', 'parts_stock.withdraw', 'parts_stock.add', 'parts_stock.move']
|
||||||
create:
|
create:
|
||||||
label: "perm.create"
|
label: "perm.create"
|
||||||
alsoSet: ['read', 'edit']
|
alsoSet: ['read', 'edit']
|
||||||
|
|
|
@ -32,6 +32,7 @@ use App\Services\ImportExportSystem\EntityExporter;
|
||||||
use App\Services\ImportExportSystem\EntityImporter;
|
use App\Services\ImportExportSystem\EntityImporter;
|
||||||
use App\Services\Trees\StructuralElementRecursionHelper;
|
use App\Services\Trees\StructuralElementRecursionHelper;
|
||||||
use App\Services\UserSystem\PermissionPresetsHelper;
|
use App\Services\UserSystem\PermissionPresetsHelper;
|
||||||
|
use App\Services\UserSystem\PermissionSchemaUpdater;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
@ -54,8 +55,11 @@ class GroupController extends BaseAdminController
|
||||||
* @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="group_edit")
|
* @Route("/{id}/edit/{timestamp}", requirements={"id"="\d+"}, name="group_edit")
|
||||||
* @Route("/{id}/", requirements={"id"="\d+"})
|
* @Route("/{id}/", requirements={"id"="\d+"})
|
||||||
*/
|
*/
|
||||||
public function edit(Group $entity, Request $request, EntityManagerInterface $em, PermissionPresetsHelper $permissionPresetsHelper, ?string $timestamp = null): Response
|
public function edit(Group $entity, Request $request, EntityManagerInterface $em, PermissionPresetsHelper $permissionPresetsHelper, PermissionSchemaUpdater $permissionSchemaUpdater, ?string $timestamp = null): Response
|
||||||
{
|
{
|
||||||
|
//Do an upgrade of the permission schema if needed (so the user can see the permissions a user get on next request (even if it was not done yet)
|
||||||
|
$permissionSchemaUpdater->groupUpgradeSchemaRecursively($entity);
|
||||||
|
|
||||||
//Handle permissions presets
|
//Handle permissions presets
|
||||||
if ($request->request->has('permission_preset')) {
|
if ($request->request->has('permission_preset')) {
|
||||||
$this->denyAccessUnlessGranted('edit_permissions', $entity);
|
$this->denyAccessUnlessGranted('edit_permissions', $entity);
|
||||||
|
|
|
@ -35,6 +35,7 @@ use App\Services\ImportExportSystem\EntityExporter;
|
||||||
use App\Services\ImportExportSystem\EntityImporter;
|
use App\Services\ImportExportSystem\EntityImporter;
|
||||||
use App\Services\Trees\StructuralElementRecursionHelper;
|
use App\Services\Trees\StructuralElementRecursionHelper;
|
||||||
use App\Services\UserSystem\PermissionPresetsHelper;
|
use App\Services\UserSystem\PermissionPresetsHelper;
|
||||||
|
use App\Services\UserSystem\PermissionSchemaUpdater;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Exception;
|
use Exception;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
@ -82,10 +83,12 @@ class UserController extends AdminPages\BaseAdminController
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function edit(User $entity, Request $request, EntityManagerInterface $em, PermissionPresetsHelper $permissionPresetsHelper, ?string $timestamp = null): Response
|
public function edit(User $entity, Request $request, EntityManagerInterface $em, PermissionPresetsHelper $permissionPresetsHelper, PermissionSchemaUpdater $permissionSchemaUpdater, ?string $timestamp = null): Response
|
||||||
{
|
{
|
||||||
//Handle 2FA disabling
|
//Do an upgrade of the permission schema if needed (so the user can see the permissions a user get on next request (even if it was not done yet)
|
||||||
|
$permissionSchemaUpdater->userUpgradeSchemaRecursively($entity);
|
||||||
|
|
||||||
|
//Handle 2FA disabling
|
||||||
if ($request->request->has('reset_2fa')) {
|
if ($request->request->has('reset_2fa')) {
|
||||||
//Check if the admin has the needed permissions
|
//Check if the admin has the needed permissions
|
||||||
$this->denyAccessUnlessGranted('set_password', $entity);
|
$this->denyAccessUnlessGranted('set_password', $entity);
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\EventSubscriber\UserSystem;
|
||||||
|
|
||||||
|
use App\Entity\UserSystem\User;
|
||||||
|
use App\Services\UserSystem\PermissionSchemaUpdater;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
|
||||||
|
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||||
|
use Symfony\Component\HttpKernel\KernelEvents;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The purpose of this event subscriber is to check if the permission schema of the current user is up to date and upgrade it automatically if needed.
|
||||||
|
*/
|
||||||
|
class UpgradePermissionsSchemaSubscriber implements EventSubscriberInterface
|
||||||
|
{
|
||||||
|
private Security $security;
|
||||||
|
private PermissionSchemaUpdater $permissionSchemaUpdater;
|
||||||
|
private EntityManagerInterface $entityManager;
|
||||||
|
private FlashBagInterface $flashBag;
|
||||||
|
|
||||||
|
public function __construct(Security $security, PermissionSchemaUpdater $permissionSchemaUpdater, EntityManagerInterface $entityManager, FlashBagInterface $flashBag)
|
||||||
|
{
|
||||||
|
$this->security = $security;
|
||||||
|
$this->permissionSchemaUpdater = $permissionSchemaUpdater;
|
||||||
|
$this->entityManager = $entityManager;
|
||||||
|
$this->flashBag = $flashBag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onRequest(RequestEvent $event): void
|
||||||
|
{
|
||||||
|
if (!$event->isMainRequest()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $this->security->getUser();
|
||||||
|
if (null === $user) {
|
||||||
|
//Retrieve anonymous user
|
||||||
|
$user = $this->entityManager->getRepository(User::class)->getAnonymousUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->permissionSchemaUpdater->isSchemaUpdateNeeded($user)) {
|
||||||
|
$this->permissionSchemaUpdater->userUpgradeSchemaRecursively($user);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
$this->flashBag->add('notice', 'user.permissions_schema_updated');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getSubscribedEvents(): array
|
||||||
|
{
|
||||||
|
return [KernelEvents::REQUEST => 'onRequest'];
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,9 @@
|
||||||
|
|
||||||
namespace App\Services\UserSystem;
|
namespace App\Services\UserSystem;
|
||||||
|
|
||||||
|
use App\Entity\UserSystem\Group;
|
||||||
use App\Entity\UserSystem\PermissionData;
|
use App\Entity\UserSystem\PermissionData;
|
||||||
|
use App\Entity\UserSystem\User;
|
||||||
use App\Security\Interfaces\HasPermissionsInterface;
|
use App\Security\Interfaces\HasPermissionsInterface;
|
||||||
|
|
||||||
class PermissionSchemaUpdater
|
class PermissionSchemaUpdater
|
||||||
|
@ -42,7 +44,8 @@ class PermissionSchemaUpdater
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upgrades the permission schema of the given user/group to the chosen version
|
* Upgrades the permission schema of the given user/group to the chosen version.
|
||||||
|
* Please note that this function does not flush the changes to DB!
|
||||||
* @param HasPermissionsInterface $holder
|
* @param HasPermissionsInterface $holder
|
||||||
* @param int $target_version
|
* @param int $target_version
|
||||||
* @return bool True, if an upgrade was done, false if it was not needed.
|
* @return bool True, if an upgrade was done, false if it was not needed.
|
||||||
|
@ -76,6 +79,42 @@ class PermissionSchemaUpdater
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upgrades the permission schema of the given group and all of its parent groups to the chosen version.
|
||||||
|
* Please note that this function does not flush the changes to DB!
|
||||||
|
* @param Group $group
|
||||||
|
* @param int $target_version
|
||||||
|
* @return bool True if an upgrade was done, false if it was not needed.
|
||||||
|
*/
|
||||||
|
public function groupUpgradeSchemaRecursively(Group $group, int $target_version = PermissionData::CURRENT_SCHEMA_VERSION): bool
|
||||||
|
{
|
||||||
|
$updated = $this->upgradeSchema($group, $target_version);
|
||||||
|
|
||||||
|
/** @var Group $parent */
|
||||||
|
$parent = $group->getParent();
|
||||||
|
while ($parent) {
|
||||||
|
$updated = $this->upgradeSchema($parent, $target_version) || $updated;
|
||||||
|
$parent = $parent->getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upgrades the permissions schema of the given users and its parent (including parent groups) to the chosen version.
|
||||||
|
* Please note that this function does not flush the changes to DB!
|
||||||
|
* @param User $user
|
||||||
|
* @param int $target_version
|
||||||
|
* @return bool True if an upgrade was done, false if it was not needed.
|
||||||
|
*/
|
||||||
|
public function userUpgradeSchemaRecursively(User $user, int $target_version = PermissionData::CURRENT_SCHEMA_VERSION): bool
|
||||||
|
{
|
||||||
|
$updated = $this->upgradeSchema($user, $target_version);
|
||||||
|
$updated = $this->groupUpgradeSchemaRecursively($user->getGroup(), $target_version) || $updated;
|
||||||
|
|
||||||
|
return $updated;
|
||||||
|
}
|
||||||
|
|
||||||
private function upgradeSchemaToVersion1(HasPermissionsInterface $holder): void
|
private function upgradeSchemaToVersion1(HasPermissionsInterface $holder): void
|
||||||
{
|
{
|
||||||
//Use the part edit permission to set the preset value for the new part stock permission
|
//Use the part edit permission to set the preset value for the new part stock permission
|
||||||
|
|
|
@ -10217,5 +10217,11 @@ Element 3</target>
|
||||||
<target>Move parts between lots</target>
|
<target>Move parts between lots</target>
|
||||||
</segment>
|
</segment>
|
||||||
</unit>
|
</unit>
|
||||||
|
<unit id="DQ_FAfi" name="user.permissions_schema_updated">
|
||||||
|
<segment>
|
||||||
|
<source>user.permissions_schema_updated</source>
|
||||||
|
<target>The permission schema of your user were upgraded to the latest version.</target>
|
||||||
|
</segment>
|
||||||
|
</unit>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue