diff --git a/assets/css/app.css b/assets/css/app.css index f6b3ada5..7d624435 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -320,6 +320,10 @@ showing the sidebar (on devices with md or higher) } } +.not-allowed { + cursor: not-allowed !important; +} + /************************************** btn-xs btn-xs diff --git a/config/permissions.yaml b/config/permissions.yaml index 43e21fea..bdac5571 100644 --- a/config/permissions.yaml +++ b/config/permissions.yaml @@ -67,6 +67,10 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co show_history: label: "perm.part.show_history" bit: 30 + revert_element: + label: "perm.revert_elements" + bit: 32 + alsoSet: ["read", "edit", "create", "delete", "show_history"] parts_name: &PART_ATTRIBUTE # We define a template here, that we can use for all part attributes. label: "perm.part.name" @@ -154,8 +158,31 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co label: "perm.part.lots" parts_attachments: - <<: *PART_MULTI_ATTRIBUTE + group: "structures" label: "perm.part.attachments" + operations: + read: + label: "perm.read" + bit: 0 + edit: + label: "perm.edit" + bit: 2 + alsoSet: 'read' + create: + label: "perm.create" + bit: 4 + alsoSet: ['read', 'edit'] + delete: + label: "perm.delete" + bit: 6 + alsoSet: ['read'] + show_history: + label: "perm.show_history" + bit: 8 + revert_element: + label: "perm.revert_elements" + bit: 10 + alsoSet: ["read", "edit", "create", "delete", "show_history"] parts_order: <<: *PART_ATTRIBUTE @@ -189,6 +216,13 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co show_users: label: "perm.show_users" bit: 12 + show_history: + label: "perm.show_history" + bit: 14 + revert_element: + label: "perm.revert_elements" + bit: 16 + alsoSet: ["read", "edit", "create", "delete", "show_history"] footprints: <<: *PART_CONTAINING @@ -243,6 +277,12 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co statistics: label: "perm.tools.statistics" bit: 10 + lastActivity: + label: "perm.tools.lastActivity" + bit: 12 + timetravel: + label: "perm.tools.timeTravel" + bit: 14 groups: label: "perm.groups" @@ -270,6 +310,13 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co label: "perm.edit_permissions" alsoSet: ['read', 'edit'] bit: 10 + show_history: + label: "perm.show_history" + bit: 12 + revert_element: + label: "perm.revert_elements" + bit: 14 + alsoSet: ["read", "edit", "create", "delete", "move", "edit_permissions", "show_history"] users: label: "perm.users" @@ -309,6 +356,13 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co change_user_settings: label: "perm.users.change_user_settings" bit: 16 + show_history: + label: "perm.show_history" + bit: 18 + revert_element: + label: "perm.revert_elements" + bit: 20 + alsoSet: ["read", "edit", "create", "delete", "move", "edit_permissions", "show_history", "edit_infos", "change_group", "edit_username"] database: label: "perm.database" diff --git a/src/Controller/AdminPages/BaseAdminController.php b/src/Controller/AdminPages/BaseAdminController.php index ec728b38..73f56907 100644 --- a/src/Controller/AdminPages/BaseAdminController.php +++ b/src/Controller/AdminPages/BaseAdminController.php @@ -89,9 +89,9 @@ abstract class BaseAdminController extends AbstractController protected $dataTableFactory; public function __construct(TranslatorInterface $translator, UserPasswordEncoderInterface $passwordEncoder, - AttachmentManager $attachmentHelper, AttachmentSubmitHandler $attachmentSubmitHandler, - EventCommentHelper $commentHelper, HistoryHelper $historyHelper, TimeTravel $timeTravel, - DataTableFactory $dataTableFactory) + AttachmentManager $attachmentHelper, AttachmentSubmitHandler $attachmentSubmitHandler, + EventCommentHelper $commentHelper, HistoryHelper $historyHelper, TimeTravel $timeTravel, + DataTableFactory $dataTableFactory) { if ('' === $this->entity_class || '' === $this->form_class || '' === $this->twig_template || '' === $this->route_base) { throw new InvalidArgumentException('You have to override the $entity_class, $form_class, $route_base and $twig_template value in your subclasss!'); @@ -119,6 +119,8 @@ abstract class BaseAdminController extends AbstractController $timeTravel_timestamp = null; if ($timestamp !== null) { + $this->denyAccessUnlessGranted('@tools.timeTravel'); + $this->denyAccessUnlessGranted('show_history', $part); //If the timestamp only contains numbers interpret it as unix timestamp if (ctype_digit($timestamp)) { $timeTravel_timestamp = new \DateTime(); @@ -129,14 +131,22 @@ abstract class BaseAdminController extends AbstractController $this->timeTravel->revertEntityToTimestamp($entity, $timeTravel_timestamp); } - $table = $this->dataTableFactory->createFromType(LogDataTable::class, [ - 'filter_elements' => $this->historyHelper->getAssociatedElements($entity), - 'mode' => 'element_history' - ], ['pageLength' => 10]) - ->handleRequest($request); + if ($this->isGranted('show_history', $entity) ) { + $table = $this->dataTableFactory->createFromType( + LogDataTable::class, + [ + 'filter_elements' => $this->historyHelper->getAssociatedElements($entity), + 'mode' => 'element_history' + ], + ['pageLength' => 10] + ) + ->handleRequest($request); - if ($table->isCallback()) { - return $table->getResponse(); + if ($table->isCallback()) { + return $table->getResponse(); + } + } else { + $table = null; } $form = $this->createForm($this->form_class, $entity, [ diff --git a/src/Controller/HomepageController.php b/src/Controller/HomepageController.php index 33314d78..8e6732c0 100644 --- a/src/Controller/HomepageController.php +++ b/src/Controller/HomepageController.php @@ -86,13 +86,21 @@ class HomepageController extends AbstractController */ public function homepage(Request $request, GitVersionInfo $versionInfo): Response { - $table = $this->dataTable->createFromType(LogDataTable::class, [ - 'mode' => 'last_activity' - ], ['pageLength' => 10]) - ->handleRequest($request); + if ($this->isGranted("@tools.lastActivity")) { + $table = $this->dataTable->createFromType( + LogDataTable::class, + [ + 'mode' => 'last_activity' + ], + ['pageLength' => 10] + ) + ->handleRequest($request); - if ($table->isCallback()) { - return $table->getResponse(); + if ($table->isCallback()) { + return $table->getResponse(); + } + } else { + $table = null; } return $this->render('homepage.html.twig', [ diff --git a/src/Controller/LogController.php b/src/Controller/LogController.php index 09b3be2f..1db56664 100644 --- a/src/Controller/LogController.php +++ b/src/Controller/LogController.php @@ -121,6 +121,8 @@ class LogController extends AbstractController throw new \InvalidArgumentException('No log entry with the given ID is existing!'); } + $this->denyAccessUnlessGranted('revert_element', $log_element->getTargetClass()); + $eventUndoHelper->setMode($mode); $eventUndoHelper->setUndoneEvent($log_element); diff --git a/src/Controller/PartController.php b/src/Controller/PartController.php index 08a26560..b8bcf8ee 100644 --- a/src/Controller/PartController.php +++ b/src/Controller/PartController.php @@ -98,6 +98,8 @@ class PartController extends AbstractController $timeTravel_timestamp = null; if ($timestamp !== null) { + $this->denyAccessUnlessGranted('@tools.timeTravel'); + $this->denyAccessUnlessGranted('show_history', $part); //If the timestamp only contains numbers interpret it as unix timestamp if (ctype_digit($timestamp)) { $timeTravel_timestamp = new \DateTime(); @@ -108,14 +110,18 @@ class PartController extends AbstractController $timeTravel->revertEntityToTimestamp($part, $timeTravel_timestamp); } - $table = $dataTable->createFromType(LogDataTable::class, [ - 'filter_elements' => $historyHelper->getAssociatedElements($part), - 'mode' => 'element_history' - ], ['pageLength' => 10]) - ->handleRequest($request); + if ($this->isGranted('show_history', $part) ) { + $table = $dataTable->createFromType(LogDataTable::class, [ + 'filter_elements' => $historyHelper->getAssociatedElements($part), + 'mode' => 'element_history' + ], ['pageLength' => 10]) + ->handleRequest($request); - if ($table->isCallback()) { - return $table->getResponse(); + if ($table->isCallback()) { + return $table->getResponse(); + } + } else { + $table = null; } return $this->render( diff --git a/src/DataTables/Column/IconLinkColumn.php b/src/DataTables/Column/IconLinkColumn.php index 32577f83..54859e33 100644 --- a/src/DataTables/Column/IconLinkColumn.php +++ b/src/DataTables/Column/IconLinkColumn.php @@ -42,11 +42,13 @@ class IconLinkColumn extends AbstractColumn 'icon' => 'fas fa-fw fa-edit', 'title' => null, 'href' => null, + 'disabled' => false, ]); $resolver->setAllowedTypes('title', ['null', 'string', 'callable']); $resolver->setAllowedTypes('icon', ['null', 'string', 'callable']); $resolver->setAllowedTypes('href', ['null', 'string', 'callable']); + $resolver->setAllowedTypes('disabled', ['bool', 'callable']); return $this; } @@ -56,10 +58,12 @@ class IconLinkColumn extends AbstractColumn $href = $this->getHref($value, $context); $icon = $this->getIcon($value, $context); $title = $this->getTitle($value, $context); + $disabled = $this->getDisabled($value, $context); if ($href !== null) { return sprintf( - '', + '', + $disabled ? 'disabled' : '', $href, $title, $icon @@ -69,6 +73,18 @@ class IconLinkColumn extends AbstractColumn return ""; } + protected function getDisabled($value, $context): bool + { + $provider = $this->options['disabled']; + if (is_bool($provider)) { + return $provider; + } + if (is_callable($provider)) { + return call_user_func($provider, $value, $context); + } + return false; + } + protected function getHref($value, $context): ?string { $provider = $this->options['href']; diff --git a/src/DataTables/Column/RevertLogColumn.php b/src/DataTables/Column/RevertLogColumn.php index 1ea451e3..09b78d4c 100644 --- a/src/DataTables/Column/RevertLogColumn.php +++ b/src/DataTables/Column/RevertLogColumn.php @@ -27,15 +27,18 @@ use App\Entity\LogSystem\ElementCreatedLogEntry; use App\Entity\LogSystem\ElementDeletedLogEntry; use App\Entity\LogSystem\ElementEditedLogEntry; use Omines\DataTablesBundle\Column\AbstractColumn; +use Symfony\Component\Security\Core\Security; use Symfony\Contracts\Translation\TranslatorInterface; class RevertLogColumn extends AbstractColumn { protected $translator; + protected $security; - public function __construct(TranslatorInterface $translator) + public function __construct(TranslatorInterface $translator, Security $security) { $this->translator = $translator; + $this->security = $security; } /** @@ -65,17 +68,21 @@ class RevertLogColumn extends AbstractColumn return ''; } + $disabled = !$this->security->isGranted('revert_element', $context->getTargetClass()); + $tmp = '
'; $tmp .= sprintf( - '', + '', $context->getID(), + $disabled ? 'disabled' : '', $icon, $title ); $tmp .= sprintf( - '', + '', $context->getID(), + $disabled ? 'disabled' : '', $this->translator->trans('log.undo.revert') ); diff --git a/src/DataTables/LogDataTable.php b/src/DataTables/LogDataTable.php index ea2e9255..ad519cb5 100644 --- a/src/DataTables/LogDataTable.php +++ b/src/DataTables/LogDataTable.php @@ -66,6 +66,7 @@ use Omines\DataTablesBundle\DataTableTypeInterface; use Psr\Log\LogLevel; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Security\Core\Security; use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Flex\Options; @@ -76,15 +77,17 @@ class LogDataTable implements DataTableTypeInterface protected $urlGenerator; protected $entityURLGenerator; protected $logRepo; + protected $security; public function __construct(ElementTypeNameGenerator $elementTypeNameGenerator, TranslatorInterface $translator, - UrlGeneratorInterface $urlGenerator, EntityURLGenerator $entityURLGenerator, EntityManagerInterface $entityManager) + UrlGeneratorInterface $urlGenerator, EntityURLGenerator $entityURLGenerator, EntityManagerInterface $entityManager, Security $security) { $this->elementTypeNameGenerator = $elementTypeNameGenerator; $this->translator = $translator; $this->urlGenerator = $urlGenerator; $this->entityURLGenerator = $entityURLGenerator; $this->logRepo = $entityManager->getRepository(AbstractLogEntry::class); + $this->security = $security; } public function configureOptions(OptionsResolver $optionsResolver) @@ -235,7 +238,13 @@ class LogDataTable implements DataTableTypeInterface } } return null; + }, + 'disabled' => function ($value, AbstractLogEntry $context) { + return + !$this->security->isGranted('@tools.timetravel') + || !$this->security->isGranted('show_history', $context->getTargetClass()); } + ]); $dataTable->add('actionRevert', RevertLogColumn::class, [ diff --git a/src/Entity/UserSystem/PermissionsEmbed.php b/src/Entity/UserSystem/PermissionsEmbed.php index 99c93427..c6b01782 100644 --- a/src/Entity/UserSystem/PermissionsEmbed.php +++ b/src/Entity/UserSystem/PermissionsEmbed.php @@ -481,7 +481,7 @@ class PermissionsEmbed */ final protected static function readBitPair($data, int $n): int { - Assert::lessThanEq($n, 31, '$n must be smaller than 32, because only a 32bit int is used! Got %s.'); + //Assert::lessThanEq($n, 31, '$n must be smaller than 32, because only a 32bit int is used! Got %s.'); if (0 !== $n % 2) { throw new InvalidArgumentException('$n must be dividable by 2, because we address bit pairs here!'); } @@ -501,7 +501,7 @@ class PermissionsEmbed */ final protected static function writeBitPair(int $data, int $n, int $new): int { - Assert::lessThanEq($n, 31, '$n must be smaller than 32, because only a 32bit int is used! Got %s.'); + //Assert::lessThanEq($n, 31, '$n must be smaller than 32, because only a 32bit int is used! Got %s.'); Assert::lessThanEq($new, 3, '$new must be smaller than 3, because a bit pair is written! Got %s.'); Assert::greaterThanEq($new, 0, '$new must not be negative, because a bit pair is written! Got %s.'); diff --git a/src/Security/Voter/AttachmentVoter.php b/src/Security/Voter/AttachmentVoter.php index 01727806..07cc9c25 100644 --- a/src/Security/Voter/AttachmentVoter.php +++ b/src/Security/Voter/AttachmentVoter.php @@ -58,11 +58,7 @@ class AttachmentVoter extends ExtendedVoter */ protected function voteOnUser($attribute, $subject, User $user): bool { - if ($subject instanceof Attachment) { - return $this->resolver->inherit($user, 'parts_attachments', $attribute) ?? false; - } - - return false; + return $this->resolver->inherit($user, 'parts_attachments', $attribute) ?? false; } /** @@ -75,10 +71,11 @@ class AttachmentVoter extends ExtendedVoter */ protected function supports($attribute, $subject) { - if ($subject instanceof Attachment) { + if (is_a($subject, Attachment::class, true)) { return in_array($attribute, $this->resolver->listOperationsForPermission('parts_attachments'), false); } + //Allow class name as subject return false; } } diff --git a/src/Security/Voter/GroupVoter.php b/src/Security/Voter/GroupVoter.php index 0b88b8a0..0201cbe5 100644 --- a/src/Security/Voter/GroupVoter.php +++ b/src/Security/Voter/GroupVoter.php @@ -57,11 +57,7 @@ class GroupVoter extends ExtendedVoter */ protected function voteOnUser($attribute, $subject, User $user): bool { - if ($subject instanceof Group) { - return $this->resolver->inherit($user, 'groups', $attribute) ?? false; - } - - return false; + return $this->resolver->inherit($user, 'groups', $attribute) ?? false; } /** @@ -74,7 +70,7 @@ class GroupVoter extends ExtendedVoter */ protected function supports($attribute, $subject) { - if ($subject instanceof Group) { + if (is_a($subject, Group::class, true)) { return $this->resolver->isValidOperation('groups', $attribute); } diff --git a/src/Security/Voter/LogEntryVoter.php b/src/Security/Voter/LogEntryVoter.php index cb1c54a1..cdc3f1c8 100644 --- a/src/Security/Voter/LogEntryVoter.php +++ b/src/Security/Voter/LogEntryVoter.php @@ -51,25 +51,21 @@ class LogEntryVoter extends ExtendedVoter protected function voteOnUser($attribute, $subject, User $user): bool { - if ($subject instanceof AbstractLogEntry) { - if ('delete' === $attribute) { - return $this->resolver->inherit($user, 'system', 'delete_logs') ?? false; - } - - if ('read' === $attribute) { - //Allow read of the users own log entries - if ( - $subject->getUser() === $user - && $this->resolver->inherit($user, 'self', 'show_logs') - ) { - return true; - } - - return $this->resolver->inherit($user, 'system', 'show_logs') ?? false; - } + if ('delete' === $attribute) { + return $this->resolver->inherit($user, 'system', 'delete_logs') ?? false; } - return false; + if ('read' === $attribute) { + //Allow read of the users own log entries + if ( + $subject->getUser() === $user + && $this->resolver->inherit($user, 'self', 'show_logs') + ) { + return true; + } + + return $this->resolver->inherit($user, 'system', 'show_logs') ?? false; + } } protected function supports($attribute, $subject) diff --git a/src/Security/Voter/OrderdetailVoter.php b/src/Security/Voter/OrderdetailVoter.php new file mode 100644 index 00000000..d06215f9 --- /dev/null +++ b/src/Security/Voter/OrderdetailVoter.php @@ -0,0 +1,57 @@ +. + */ + +namespace App\Security\Voter; + + +use App\Entity\Parts\PartLot; +use App\Entity\PriceInformations\Orderdetail; +use App\Entity\UserSystem\User; + +class OrderdetailVoter extends ExtendedVoter +{ + /** @var string[] When this permsission are encountered, they are checked on part */ + protected const PART_PERMS = ['show_history', 'revert_element']; + + /** + * @inheritDoc + */ + protected function voteOnUser($attribute, $subject, User $user): bool + { + if (in_array($attribute, self::PART_PERMS, true)) { + return $this->resolver->inherit($user, 'parts', $attribute) ?? false; + } + + return $this->resolver->inherit($user, 'parts_orderdetails', $attribute) ?? false; + } + + /** + * @inheritDoc + */ + protected function supports($attribute, $subject) + { + if (is_a($subject, Orderdetail::class, true)) { + return in_array($attribute, array_merge( + self::PART_PERMS, + $this->resolver->listOperationsForPermission('parts_orderdetails') + ), true); + } + } +} \ No newline at end of file diff --git a/src/Security/Voter/PartLotVoter.php b/src/Security/Voter/PartLotVoter.php new file mode 100644 index 00000000..6fc372aa --- /dev/null +++ b/src/Security/Voter/PartLotVoter.php @@ -0,0 +1,56 @@ +. + */ + +namespace App\Security\Voter; + + +use App\Entity\Parts\PartLot; +use App\Entity\UserSystem\User; + +class PartLotVoter extends ExtendedVoter +{ + /** @var string[] When this permsission are encountered, they are checked on part */ + protected const PART_PERMS = ['show_history', 'revert_element']; + + /** + * @inheritDoc + */ + protected function voteOnUser($attribute, $subject, User $user): bool + { + if (in_array($attribute, self::PART_PERMS, true)) { + return $this->resolver->inherit($user, 'parts', $attribute) ?? false; + } + + return $this->resolver->inherit($user, 'parts_lots', $attribute) ?? false; + } + + /** + * @inheritDoc + */ + protected function supports($attribute, $subject) + { + if (is_a($subject, PartLot::class, true)) { + return in_array($attribute, array_merge( + self::PART_PERMS, + $this->resolver->listOperationsForPermission('parts_lots') + ), true); + } + } +} \ No newline at end of file diff --git a/src/Security/Voter/PartVoter.php b/src/Security/Voter/PartVoter.php index d7d375cc..f829f557 100644 --- a/src/Security/Voter/PartVoter.php +++ b/src/Security/Voter/PartVoter.php @@ -57,11 +57,7 @@ class PartVoter extends ExtendedVoter protected function supports($attribute, $subject) { - // replace with your own logic - // https://symfony.com/doc/current/security/voters.html - //return ($subject instanceof Part || in_array($subject, ['PERM_parts', 'PERM_parts_name'])); - - if ($subject instanceof Part) { + if (is_a($subject, Part::class, true)) { //Check if a sub permission should be checked -> $attribute has format name.edit if (false !== strpos($attribute, '.')) { [$perm, $op] = explode('.', $attribute); @@ -72,24 +68,21 @@ class PartVoter extends ExtendedVoter return $this->resolver->isValidOperation('parts', $attribute); } + //Allow class name as subject return false; } protected function voteOnUser($attribute, $subject, User $user): bool { - if ($subject instanceof Part) { - //Check for sub permissions - if (false !== strpos($attribute, '.')) { - [$perm, $op] = explode('.', $attribute); + //Check for sub permissions + if (false !== strpos($attribute, '.')) { + [$perm, $op] = explode('.', $attribute); - return $this->resolver->inherit($user, 'parts_'.$perm, $op) ?? false; - } - - //Null concealing operator means, that no - return $this->resolver->inherit($user, 'parts', $attribute) ?? false; + return $this->resolver->inherit($user, 'parts_'.$perm, $op) ?? false; } - //Deny access by default. - return false; + //Null concealing operator means, that no + return $this->resolver->inherit($user, 'parts', $attribute) ?? false; + } } diff --git a/src/Security/Voter/PricedetailVoter.php b/src/Security/Voter/PricedetailVoter.php new file mode 100644 index 00000000..19972fad --- /dev/null +++ b/src/Security/Voter/PricedetailVoter.php @@ -0,0 +1,57 @@ +. + */ + +namespace App\Security\Voter; + + +use App\Entity\Parts\PartLot; +use App\Entity\PriceInformations\Pricedetail; +use App\Entity\UserSystem\User; + +class PricedetailVoter extends ExtendedVoter +{ + /** @var string[] When this permsission are encountered, they are checked on part */ + protected const PART_PERMS = ['show_history', 'revert_element']; + + /** + * @inheritDoc + */ + protected function voteOnUser($attribute, $subject, User $user): bool + { + if (in_array($attribute, self::PART_PERMS, true)) { + return $this->resolver->inherit($user, 'parts', $attribute) ?? false; + } + + return $this->resolver->inherit($user, 'parts_prices', $attribute) ?? false; + } + + /** + * @inheritDoc + */ + protected function supports($attribute, $subject) + { + if (is_a($subject, Pricedetail::class, true)) { + return in_array($attribute, array_merge( + self::PART_PERMS, + $this->resolver->listOperationsForPermission('parts_prices') + ), true); + } + } +} \ No newline at end of file diff --git a/src/Security/Voter/StructureVoter.php b/src/Security/Voter/StructureVoter.php index e2699b48..d5d6eb51 100644 --- a/src/Security/Voter/StructureVoter.php +++ b/src/Security/Voter/StructureVoter.php @@ -43,11 +43,13 @@ declare(strict_types=1); namespace App\Security\Voter; use App\Entity\Attachments\AttachmentType; +use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Devices\Device; use App\Entity\Parts\Category; use App\Entity\Parts\Footprint; use App\Entity\Parts\Manufacturer; use App\Entity\Parts\MeasurementUnit; +use App\Entity\Parts\Part; use App\Entity\Parts\Storelocation; use App\Entity\Parts\Supplier; use App\Entity\PriceInformations\Currency; @@ -67,24 +69,29 @@ class StructureVoter extends ExtendedVoter */ protected function supports($attribute, $subject) { - if (is_object($subject)) { + if (is_object($subject) || is_string($subject)) { $permission_name = $this->instanceToPermissionName($subject); //If permission name is null, then the subject is not supported return (null !== $permission_name) && $this->resolver->isValidOperation($permission_name, $attribute); } + return false; } /** * Maps a instance type to the permission name. * - * @param mixed $subject The subject for which the permission name should be generated + * @param object|string $subject The subject for which the permission name should be generated * * @return string|null the name of the permission for the subject's type or null, if the subject is not supported */ protected function instanceToPermissionName($subject): ?string { - $class_name = get_class($subject); + if (!is_string($subject)) { + $class_name = get_class($subject); + } else { + $class_name = $subject; + } switch ($class_name) { case AttachmentType::class: return 'attachment_types'; diff --git a/src/Security/Voter/UserVoter.php b/src/Security/Voter/UserVoter.php index d724a2e6..de7d165b 100644 --- a/src/Security/Voter/UserVoter.php +++ b/src/Security/Voter/UserVoter.php @@ -57,11 +57,11 @@ class UserVoter extends ExtendedVoter */ protected function supports($attribute, $subject) { - if ($subject instanceof User) { + if (is_a($subject, User::class, true)) { return in_array($attribute, array_merge( $this->resolver->listOperationsForPermission('users'), $this->resolver->listOperationsForPermission('self')), - false + false ); } @@ -89,10 +89,11 @@ class UserVoter extends ExtendedVoter return $tmp; } } - //Else just check users permission: - if ($this->resolver->isValidOperation('users', $attribute)) { - return $this->resolver->inherit($user, 'users', $attribute) ?? false; - } + } + + //Else just check users permission: + if ($this->resolver->isValidOperation('users', $attribute)) { + return $this->resolver->inherit($user, 'users', $attribute) ?? false; } return false; diff --git a/templates/AdminPages/EntityAdminBase.html.twig b/templates/AdminPages/EntityAdminBase.html.twig index ce2ef29d..f298b841 100644 --- a/templates/AdminPages/EntityAdminBase.html.twig +++ b/templates/AdminPages/EntityAdminBase.html.twig @@ -59,8 +59,8 @@
+ {% if datatable is not null %}
{% trans %}homepage.last_activity{% endtrans %}
{% include "LogSystem/_log_table.html.twig" %}
+ {% endif %} {% endblock %} \ No newline at end of file