<?php
namespace Harmonizely\Service\SuperAdmin\Panel\AccessVoters;
use Harmonizely\Types\SuperAdmin\UserRole;
use Harmonizely\Entity\SuperAdmin\UserEntity;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
class UserVoter extends AbstractVoter
{
/**
* Resource name
*/
const RESOURCE_NAME = 'user';
/**
* Edit user
*/
const EDIT = 'user_edit';
/**
* Block user
*/
const BLOCK = 'user_block';
/**
* View users, user
*/
const VIEW = 'user_view';
/**
* Edit self profile
*/
const EDIT_PROFILE = 'user_edit_profile';
/**
* View self profile
*/
const VIEW_PROFILE = 'user_view_profile';
/**
* Change password
*/
const CHANGE_PASSWORD = 'user_change_password';
/**
* Return resource name
*
* @return string
*/
function getResourceName(): string
{
return self::RESOURCE_NAME;
}
/**
* Return allowed attributes for current user
*
* @return array|string[]
*/
function getResourceAttributes(): array
{
return [
self::EDIT,
self::BLOCK,
self::VIEW,
self::EDIT_PROFILE,
self::VIEW_PROFILE,
self::CHANGE_PASSWORD
];
}
/**
* Return allowed attributes for current user
*
* @param UserEntity $user
* @return array|string[]
*/
function getAllowedAttributes(UserEntity $user): array
{
switch ($user->getRole()) {
case UserRole::ROLE_ADMIN:
return $this->getResourceAttributes();
case UserRole::ROLE_SYSTEM_USER:
return [self::EDIT, self::BLOCK, self::VIEW, self::VIEW_PROFILE, self::EDIT_PROFILE, self::CHANGE_PASSWORD];
default:
return [self::VIEW_PROFILE, self::EDIT_PROFILE, self::CHANGE_PASSWORD];
}
}
/**
* Determines if the attribute and subject are supported by this voter.
*
* @param string $attribute An attribute
* @param mixed $subject The subject to secure, e.g. an object the user wants to access or any other PHP type
*
* @return bool True if the attribute and subject are supported, false otherwise
*/
protected function supports($attribute, $subject): bool
{
if ($subject !== null && !($subject instanceof UserEntity)) {
return false;
}
if ($subject instanceof UserEntity && $subject->getRole() === UserRole::ROLE_SYSTEM_USER && in_array($attribute, [self::EDIT, self::BLOCK, self::CHANGE_PASSWORD])) {
return false;
}
if (!in_array($attribute, $this->getResourceAttributes())) {
return false;
}
if (!in_array($attribute, [self::VIEW, self::EDIT]) && $subject === null) {
return false;
}
return true;
}
/**
* Perform a single access check operation on a given attribute, subject and token.
* It is safe to assume that $attribute and $subject already passed the "supports()" method check.
*
* @param string $attribute
* @param mixed $subject
* @param TokenInterface $token
* @return bool
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!($user instanceof UserEntity)) {
return false;
}
if (in_array($attribute, [self::EDIT_PROFILE, self::VIEW_PROFILE])
&& $user->getId() !== $subject->getId()) {
return false;
}
return parent::voteOnAttribute($attribute, $subject, $token);
}
}