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 %}
{% include "LogSystem/_log_table.html.twig" %}
+ {% endif %}
{% endblock %}
\ No newline at end of file