<?php
namespace Crea\SecurityBundle\Voter;
use Crea\SecurityBundle\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\User\UserInterface;
class UserVoter extends Voter
{
const USER_LIST = "SECURITY_USER_LIST";
const USER_CREATE = "SECURITY_USER_CREATE";
const USER_UPDATE_PASSWORD = "SECURITY_USER_UPDATE_PASSWORD";
const USER_UPDATE = "SECURITY_USER_UPDATE";
const USER_REMOVE = "SECURITY_USER_REMOVE";
const USER_IMPERSONATE = "SECURITY_USER_IMPERSONATE";
const USER_CONNECT = "SECURITY_USER_CONNECT";
const USER_DETAIL = "SECURITY_USER_DETAIL";
const USER_ACTIVE = "SECURITY_USER_ACTIVE";
/**
* @inheritDoc
*/
protected function supports($attribute, $subject): bool
{
return in_array($attribute, [
self::USER_LIST,
self::USER_CREATE,
self::USER_UPDATE_PASSWORD,
self::USER_UPDATE,
self::USER_REMOVE,
self::USER_IMPERSONATE,
self::USER_CONNECT,
self::USER_DETAIL,
self::USER_ACTIVE,
]) && ($subject === null || $subject instanceof User);
}
/**
* @inheritDoc
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
/** @var User $loggedUser */
$loggedUser = $token->getUser();
if (!$loggedUser instanceof UserInterface)
return false;
switch ($attribute) {
case self::USER_DETAIL:
return $this->voteOnDetail($subject, $loggedUser);
case self::USER_LIST:
return $this->voteOnList($loggedUser);
case self::USER_ACTIVE:
return $this->voteOnActive($loggedUser);
case self::USER_CREATE:
return $this->voteOnCreate($loggedUser);
case self::USER_UPDATE_PASSWORD:
return $this->voteOnpassword($loggedUser);
case self::USER_UPDATE:
return $this->voteOnUpdate($subject, $loggedUser);
case self::USER_REMOVE:
return $this->voteOnRemove($subject, $loggedUser);
case self::USER_IMPERSONATE:
return $this->voteOnImpersonate($subject, $loggedUser);
case self::USER_CONNECT:
return $this->voteOnConnect($subject);
}
return false;
}
private function voteOnImpersonate($subject, UserInterface $loggedUser): bool
{
if ($subject === null) {
if (in_array(self::USER_IMPERSONATE, $loggedUser->getRoles())) {
return true;
}
} else {
/** @var User $user */
$user = $subject;
if (
in_array(self::USER_IMPERSONATE, $loggedUser->getRoles()) &&
$user->getLogin() !== $loggedUser->getUsername() &&
$this->voteOnConnect($user)
) {
return true;
}
}
return false;
}
public function voteOnConnect(?UserInterface $subject): bool
{
return $subject !== null && $subject->getProfile() !== null && $subject->isEnabled();
}
private function voteOnList(UserInterface $loggedUser): bool
{
if (in_array(self::USER_LIST, $loggedUser->getRoles())) {
return true;
}
return false;
}
private function voteOnCreate(UserInterface $loggedUser): bool
{
if (in_array(self::USER_CREATE, $loggedUser->getRoles())) {
return true;
}
return false;
}
private function voteOnPassword(UserInterface $loggedUser): bool
{
if (in_array(self::USER_UPDATE_PASSWORD, $loggedUser->getRoles())) {
return true;
}
return false;
}
private function voteOnUpdate(?UserInterface $subject, UserInterface $loggedUser): bool
{
if (!in_array(self::USER_UPDATE, $loggedUser->getRoles()))
return false;
if (null === $subject)
return true;
if ($loggedUser !== $subject)
return true;
if (in_array("ROLE_ADMIN", $loggedUser->getRoles()))
return true;
return false;
}
private function voteOnRemove(?UserInterface $subject, UserInterface $loggedUser): bool
{
if (!in_array(self::USER_REMOVE, $loggedUser->getRoles()))
return false;
if (null === $subject)
return true;
if ($loggedUser !== $subject)
return true;
return false;
}
/**
* By default, a user can see its own detail, the right let him see the other details
* @param UserInterface $subject
* @param UserInterface $loggedUser
* @return bool
*/
private function voteOnDetail(UserInterface $subject, UserInterface $loggedUser): bool
{
if ($subject->getUsername() === $loggedUser->getUsername())
return true;
if (in_array(self::USER_DETAIL, $loggedUser->getRoles()))
return true;
return false;
}
private function voteOnActive(UserInterface $loggedUser): bool
{
if (in_array(self::USER_ACTIVE, $loggedUser->getRoles())) {
return true;
}
return false;
}
}