<?php
declare(strict_types=1);
namespace App\Security\Voter\Procedure;
use App\Model\Work\Procedure\Entity\Lot\Bid\Status;
use App\ReadModel\Procedure\Bid\BidFetcher;
use App\ReadModel\Procedure\Lot\DetailView;
use App\Security\UserIdentity;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Security;
class RebidVoter extends Voter
{
public const REBID_LIST = 'rebid_list';
public const REBID_SHOW = 'rebid_show';
public const REBID_APPLY = 'rebid_apply';
public const REBID_PROTOCOL_DOCUMENT_UPLOAD = 'rebid_protocol_document_upload';
private BidFetcher $bidFetcher;
private Security $security;
public function __construct(Security $security, BidFetcher $bidFetcher)
{
$this->security = $security;
$this->bidFetcher = $bidFetcher;
}
protected function supports(string $attribute, $subject): bool
{
return in_array($attribute, [
self::REBID_SHOW,
self::REBID_APPLY,
self::REBID_LIST,
self::REBID_PROTOCOL_DOCUMENT_UPLOAD
], true);
}
/**
* @param string $attribute
* @param DetailView $subject
* @param TokenInterface $token
* @return bool
*/
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
// Moderators have full access
if ($this->security->isGranted('ROLE_MODERATOR')) {
return true;
}
$user = $token->getUser();
// Only authenticated UserIdentity can proceed
if (!$user instanceof UserIdentity) {
return false;
}
if ($user->getProfileId() === null) {
throw new AccessDeniedException('Профиль не найден. У вас недостаточно прав для совершения этого действия.');
}
/*** Список разрешенных профиль ид*/
$accessProfileIds = [];
$accessProfileIds[] = $subject->organizer_profile_id;
$findBids = $this->bidFetcher->findAllBidsByLot(
$subject->id,
[
Status::sent()->getName(),
Status::approved()->getName()
]
);
$participantIds = array_map(function ($bid) {
return $bid->getParticipantId();
}, $findBids);
$accessProfileIds = array_merge($accessProfileIds, $participantIds);
if (in_array($user->getProfileId(), $accessProfileIds) === false) {
throw new AccessDeniedException('Доступ запрещен. У вас недостаточно прав для совершения этого действия.');
}
switch ($attribute) {
case self::REBID_APPLY:
//is owner procedure
if ($subject->organizer_profile_id === $user->getProfileId()) {
throw new AccessDeniedException('Доступ запрещен. У вас недостаточно прав для совершения этого действия.');
}
break;
case self::REBID_PROTOCOL_DOCUMENT_UPLOAD:
case self::REBID_LIST:
//is not owner procedure
if ($subject->organizer_profile_id !== $user->getProfileId()) {
throw new AccessDeniedException('Доступ запрещен. У вас недостаточно прав для совершения этого действия.');
}
break;
}
return true;
}
}