diff --git a/src/Entity/User.php b/src/Entity/User.php index 11915d6c..b07c0a4a 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -47,6 +47,9 @@ use Symfony\Component\Validator\Constraints as Assert; */ class User extends NamedDBElement implements UserInterface, HasPermissionsInterface { + /** The User id of the anonymous user */ + const ID_ANONYMOUS = 1; + /** * @ORM\Id() * @ORM\GeneratedValue() @@ -128,6 +131,15 @@ class User extends NamedDBElement implements UserInterface, HasPermissionsInterf protected $permissions; + /** + * Checks if the current user, is the user which represents the not logged in (anonymous) users. + * @return bool True if this user is the anonymous user. + */ + public function isAnonymousUser() : bool + { + return $this->id === static::ID_ANONYMOUS && $this->name === 'anonymous'; + } + /** * A visual identifier that represents this user. * @@ -216,6 +228,16 @@ class User extends NamedDBElement implements UserInterface, HasPermissionsInterf * Getters ************************************************/ + public function setName(string $new_name) : NamedDBElement + { + // Anonymous user is not allowed to change its username + if(!$this->isAnonymousUser()) { + $this->name = $new_name; + } + + return $this; + } + /** * @return string */ diff --git a/src/Security/Voter/ExtendedVoter.php b/src/Security/Voter/ExtendedVoter.php new file mode 100644 index 00000000..c2af004d --- /dev/null +++ b/src/Security/Voter/ExtendedVoter.php @@ -0,0 +1,83 @@ +resolver = $resolver; + $this->entityManager = $entityManager; + } + + final protected function voteOnAttribute($attribute, $subject, TokenInterface $token) + { + $user = $token->getUser(); + // if the user is anonymous, we use the anonymous user. + if (!$user instanceof User) { + $user = $this->entityManager->find(User::class, User::ID_ANONYMOUS); + if($user === null) { + return false; + } + } + + return $this->voteOnUser($attribute, $subject, $user); + } + + /** + * Similar to voteOnAttribute, but checking for the anonymous user is already done. + * The current user (or the anonymous user) is passed by $user. + * @param $attribute + * @param $subject + * @param User $user + * @return bool + */ + abstract protected function voteOnUser($attribute, $subject, User $user) : bool; +} \ No newline at end of file diff --git a/src/Security/Voter/PartVoter.php b/src/Security/Voter/PartVoter.php index 9e6dabc9..f0fad559 100644 --- a/src/Security/Voter/PartVoter.php +++ b/src/Security/Voter/PartVoter.php @@ -18,16 +18,10 @@ use Symfony\Component\Security\Core\User\UserInterface; * * @package App\Security\Voter */ -class PartVoter extends Voter +class PartVoter extends ExtendedVoter { const READ = "read"; - protected $resolver; - - public function __construct(PermissionResolver $resolver) - { - $this->resolver = $resolver; - } protected function supports($attribute, $subject) { @@ -43,14 +37,9 @@ class PartVoter extends Voter return false; } - protected function voteOnAttribute($attribute, $subject, TokenInterface $token) - { - $user = $token->getUser(); - // if the user is anonymous, do not grant access - if (!$user instanceof User) { - return false; - } + protected function voteOnUser($attribute, $subject, User $user): bool + { if($subject instanceof Part) { //Null concealing operator means, that no return $this->resolver->inherit($user, 'parts', $attribute) ?? false;