<?php
namespace App\Security\Voter;
use App\Entity\Authorization;
use App\Entity\RealEstate;
use App\Entity\User;
use App\Manager\UserManager;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
class UserVoter extends Voter
{
public const CREATE = 'CAN_CREATE';
public const READ = 'CAN_READ';
public const EDIT = 'CAN_EDIT';
public const DELETE = 'CAN_DELETE';
public function __construct(
private Security $security,
private UserManager $userManager
) {
}
protected function supports($attribute, $subject): bool
{
$supportsAttribute = in_array($attribute, [self::CREATE, self::DELETE, self::EDIT, self::READ]);
$supportsSubject = $subject instanceof User;
return $supportsAttribute && $supportsSubject;
}
/**
* @param mixed $subject
*/
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
$user = $this->security->getUser();
if (!$user) {
return false;
}
switch ($attribute) {
case self::CREATE:
return $this->canCreate($subject, $user);
case self::READ:
return $this->canRead($subject, $user);
case self::EDIT:
return $this->canEdit($subject, $user);
case self::DELETE:
return $this->canDelete($subject, $user);
}
return false;
}
private function canCreate(User $subject, User $user): bool
{
if ($this->security->isGranted(Authorization::ROLE_ADMIN)
|| $this->security->isGranted(Authorization::ROLE_OWNER_ADMIN)
) {
return true;
}
return false;
}
private function canRead(User $subject, User $user): bool
{
if ($this->security->isGranted(Authorization::ROLE_ADMIN)) {
return true;
}
return $this->userManager->hasAccess($subject, $user);
}
/**
* Only owner can edit,
* as owner admin, we need the same company
* as simple owner, the real estate must be in the list of our realestate.
*
* @param RealEstate $realEstate
*/
private function canEdit(User $subject, User $user): bool
{
if ($this->security->isGranted(Authorization::ROLE_ADMIN)) {
return true;
}
// as a owner,we must at least have the same company of the realEstate
if ($user->getCompany()->getId() !== $subject->getCompany()->getId()) {
return false;
}
if (
$this->security->isGranted(Authorization::ROLE_OWNER_ADMIN)
|| $this->security->isGranted(Authorization::ROLE_SERVICE_PROVIDER_ADMIN)
) {
return true;
}
return false;
}
private function canDelete(User $subject, User $user): bool
{
return $this->canEdit($subject, $user);
}
}