From 90d449ea22dda13bfa3513e47661f68e7b6fd952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Wed, 11 Sep 2019 18:50:23 +0200 Subject: [PATCH] Prevent a user from lock itself out from the user system. --- src/Controller/DebugController.php | 2 + src/Entity/UserSystem/Group.php | 2 + src/Form/Permissions/PermissionsType.php | 12 ++- src/Repository/UserRepository.php | 11 +++ src/Validator/Constraints/NoLockout.php | 44 +++++++++ .../Constraints/NoLockoutValidator.php | 94 +++++++++++++++++++ 6 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 src/Validator/Constraints/NoLockout.php create mode 100644 src/Validator/Constraints/NoLockoutValidator.php diff --git a/src/Controller/DebugController.php b/src/Controller/DebugController.php index e860b7cb..cb2469da 100644 --- a/src/Controller/DebugController.php +++ b/src/Controller/DebugController.php @@ -87,5 +87,7 @@ class DebugController extends AbstractController $translator->trans('flash.notice'); $translator->trans('flash.info'); + $translator->trans('validator.noLockout'); + } } diff --git a/src/Entity/UserSystem/Group.php b/src/Entity/UserSystem/Group.php index e522ed1a..2d5eb8f2 100644 --- a/src/Entity/UserSystem/Group.php +++ b/src/Entity/UserSystem/Group.php @@ -33,6 +33,7 @@ namespace App\Entity\UserSystem; use App\Entity\Base\StructuralDBElement; use App\Security\Interfaces\HasPermissionsInterface; +use App\Validator\Constraints\ValidPermission; use Doctrine\ORM\Mapping as ORM; /** @@ -61,6 +62,7 @@ class Group extends StructuralDBElement implements HasPermissionsInterface /** @var PermissionsEmbed * @ORM\Embedded(class="PermissionsEmbed", columnPrefix="perms_") + * @ValidPermission() */ protected $permissions; diff --git a/src/Form/Permissions/PermissionsType.php b/src/Form/Permissions/PermissionsType.php index 1632ba22..bb75f8e3 100644 --- a/src/Form/Permissions/PermissionsType.php +++ b/src/Form/Permissions/PermissionsType.php @@ -33,10 +33,12 @@ namespace App\Form\Permissions; use App\Services\PermissionResolver; +use App\Validator\Constraints\NoLockout; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; +use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; class PermissionsType extends AbstractType @@ -54,8 +56,16 @@ class PermissionsType extends AbstractType public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ - 'show_legend' => true + 'show_legend' => true, + 'constraints' => function (Options $options) { + if (!$options['disabled']) { + return [new NoLockout()]; + } + return []; + } ]); + + } public function buildView(FormView $view, FormInterface $form, array $options) diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index fc446b5a..d8a3aca3 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -19,6 +19,17 @@ class UserRepository extends ServiceEntityRepository parent::__construct($registry, User::class); } + /** + * Returns the anonymous user + * @return User|null + */ + public function getAnonymousUser() + { + return $this->findOneBy([ + 'id' => User::ID_ANONYMOUS + ]); + } + // /** // * @return User[] Returns an array of User objects // */ diff --git a/src/Validator/Constraints/NoLockout.php b/src/Validator/Constraints/NoLockout.php new file mode 100644 index 00000000..4273213b --- /dev/null +++ b/src/Validator/Constraints/NoLockout.php @@ -0,0 +1,44 @@ +resolver = $resolver; + $this->perm_structure = $resolver->getPermissionStructure(); + $this->security = $security; + $this->entityManager = $entityManager; + } + + /** + * Checks if the passed value is valid. + * + * @param mixed $value The value that should be validated + * @param Constraint $constraint The constraint for the validation + */ + public function validate($value, Constraint $constraint) + { + if (!$constraint instanceof NoLockout) { + throw new UnexpectedTypeException($constraint, NoLockout::class); + } + + + $perm_holder = $value; + + //Prevent that a user revokes its own change_permission perm (prevent the user to lock out itself) + if ($perm_holder instanceof User || $perm_holder instanceof Group) { + + $user = $this->security->getUser(); + + if ($user === null) { + $user = $this->entityManager->getRepository(User::class)->getAnonymousUser(); + } + + if ($user instanceof User) { + //Check if we the change_permission permission has changed from allow to disallow + if (($this->resolver->inherit($user, 'users', 'edit_permissions') ?? false) === false) { + $this->context->addViolation($constraint->message); + } + } + } + } +} \ No newline at end of file