src/Security/Voters/Olympiad/ParticipantVoter.php line 14
<?php
namespace App\Security\Voters\Olympiad;
use App\Entity\Common\Country;
use App\Entity\Olympiad\Online\Participant;
use App\Entity\Olympiad\Online\Participant\Result;
use App\Service\Olympiads\Online\MoodleCourseChooser;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
class ParticipantVoter extends Voter
{
public const EDIT_PARTICIPANT = 'participant_edit';
public const PARTICIPANT_APPLY_TEST = 'participant_apply_test';
public const PARTICIPANT_VIEW_RESULT = 'participant_view_result';
public const PARTICIPANT_VIEW_APPLY_TEST = 'participant_view_apply_test';
public const VIEW_PARTICIPANT = 'participant_view';
private Security $security;
private EntityManagerInterface $em;
private MoodleCourseChooser $moodleCourseChooser;
public function __construct(Security $security, EntityManagerInterface $em, MoodleCourseChooser $moodleCourseChooser)
{
$this->security = $security;
$this->em = $em;
$this->moodleCourseChooser = $moodleCourseChooser;
}
/**
* 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 (!in_array($attribute, [self::EDIT_PARTICIPANT, self::VIEW_PARTICIPANT, self::PARTICIPANT_APPLY_TEST, self::PARTICIPANT_VIEW_APPLY_TEST, self::PARTICIPANT_VIEW_RESULT])) {
return false;
}
// only vote on Post objects inside this voter
if (!$subject instanceof Participant) {
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 Participant $subject
* @param TokenInterface $token
*
* @return bool
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
switch ($attribute) {
case self::EDIT_PARTICIPANT:
return ($subject->getState() == $subject::STATE_NEW
&& false == $subject->isCanceled()
&& $subject->getUser() == $token->getUser()
);
case self::VIEW_PARTICIPANT:
return $subject->getUser() == $token->getUser();
case self::PARTICIPANT_APPLY_TEST:
return $this->isApplyTest($subject, $token);
case self::PARTICIPANT_VIEW_APPLY_TEST:
return $this->isViewApplyTest($subject, $token);
case self::PARTICIPANT_VIEW_RESULT:
return $this->isViewResult($subject, $token);
}
throw new \LogicException('This code should not be reached!');
}
/**
* @param Participant $subject
* @param TokenInterface $token
* @return bool
*/
protected function isApplyTest(Participant $subject, TokenInterface $token): bool
{
/*$correctState = $subject->getState() == $subject::STATE_SEND && $subject->isCanceled() == false && $subject->isConfirmed() == true;
$correctUser = $subject->getUser() == $token->getUser();
$correctTime = false;
$now = new \DateTime();
if ($subject->getDirection()->getTestTime()->getFrom() <= $now && $subject->getDirection()->getTestTime()->getTo() >= $now) {
$correctTime = true;
}
return ($correctState && $correctUser && $correctTime)||$this->security->isGranted('ROLE_ADMIN');
*/
$correctState = $subject->isCanceled() == false && $this->isParticipantActiveState($subject);
$correctUser = $subject->getUser() == $token->getUser();
// $direction = $subject->getDirection();
$moodleCourse = $this->moodleCourseChooser->choose($subject);
if (!$moodleCourse) {
return false;
}
// dump($moodleCourse);
/* if ($direction->getTestTime()->getFrom() <= $now && $direction->getTestTime()->getTo() >= $now) {
}*/
$rulesCheck = $this->checkDirectionRules($subject);
/* $regionCorrect = false;
if ($direction->getId() == 1) {
$regionCorrect = true;
} elseif ($direction->getId() == 2) {
if ($subject->getCountry()
&& $subject->getCountry()->getId() == 173
&& $subject->getRegion()
&& $subject->getRegion()->getDistrict()->getId() == 1) {
$regionCorrect = true;
}
}*/
return ($correctState && $correctUser && $rulesCheck /*&& $regionCorrect*/) || $this->security->isGranted('ROLE_TEST_ANY_TIME');
}
/**
* @param Participant $subject
* @return bool
*/
protected function isParticipantActiveState(Participant $subject): bool
{
return in_array($subject->getState(), [Participant::STATE_ACCEPTED, Participant::STATE_SEND, Participant::STATE_NEW]);
}
/**
* @param Participant $subject
* @return bool
*/
private function checkDirectionRules(Participant $subject): bool
{
$direction = $subject->getDirection();
if ($direction->getApplyAllow() & $direction::APPLY_BY_TEST_TIME) {
$now = new \DateTime();
if ($direction->getTestTime()->getFrom() > $now || $direction->getTestTime()->getTo() < $now) {
return false;
}
// if ($direction->getTestTime()->getFrom() <= $now && $direction->getTestTime()->getTo() >= $now) {
//
// } else return false;
}
return $this->checkUserAccess($subject);
}
/**
* @param \App\Entity\Olympiad\Online\Direction|null $direction
* @param Participant $subject
* @return bool
*/
private function checkUserAccess(Participant $subject): bool
{
$direction = $subject->getDirection();
if ($direction->getApplyAllow() & $direction::APPLY_IMPLICIT) {
if (false == $subject->isApplyAllow()) {
return false;
}
}
if ($direction->getApplyAllow() & $direction::APPLY_RULE_RUSSIAN) {
$country = $subject->getCountry();
if (!$country || $country->getId() != Country::C_RUSSIA) {
return false;
}
}
if ($direction->getApplyAllow() & $direction::APPLY_RULE_REGION_CFO) {
if (false == $this->checkDistrict($subject, 1)) {
return false;
}
}
return true;
}
private function checkDistrict(Participant $participant, int $districtId): bool
{
$region = $participant->getRegion();
if (!$region || !$region->getDistrict()) {
return false;
}
return $region->getDistrict()->getId() == $districtId;
}
/**
* @param Participant $subject
* @param TokenInterface $token
* @return bool
*/
protected function isViewApplyTest(Participant $subject, TokenInterface $token): bool
{
/*$corretState = $subject->getState() == $subject::STATE_SEND && $subject->isCanceled() == false && $subject->isConfirmed() == true;
$correctUser = $subject->getUser() == $token->getUser();
$correctTime = false;
$now = new \DateTime();
if ($subject->getDirection()->getTestTime()->getFrom() <= $now && $subject->getDirection()->getTestTime()->getTo() >= $now) {
$correctTime = true;
}
return ($corretState && $correctUser && $correctTime)||$this->security->isGranted('ROLE_ADMIN');
*/
$corretState = $subject->isCanceled() == false && $this->isParticipantActiveState($subject);
$correctUser = $subject->getUser() == $token->getUser();
$moodleCourse = $this->moodleCourseChooser->choose($subject);
if (!$moodleCourse) {
return false;
}
$userAccess = $this->checkUserAccess($subject);
/* $regionCorrect = false;
if ($direction->getId() == 1) {
$regionCorrect = true;
} elseif ($direction->getId() == 2) {
if ($subject->getCountry()
&& $subject->getCountry()->getId() == 173
&& $subject->getRegion()
&& $subject->getRegion()->getDistrict()->getId() == 1) {
$regionCorrect = true;
}
}*/
return ($corretState && $correctUser && $userAccess/* && $regionCorrect*/) || $this->security->isGranted('ROLE_TEST_ANY_TIME');
}
private function isViewResult(Participant $subject, TokenInterface $token): bool
{
$resultRepo = $this->em->getRepository(Result::class);
$result = $resultRepo->find($subject);
return !!$result;
}
}