<?php
declare(strict_types=1);
namespace App\Security\Voter;
use App\Entity\Product;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class ProductVoter extends Voter
{
public const VIEW = 'view';
public const VIEW_TOOL_APPLICATIONS = 'view_tool_applications';
public const EDIT = 'edit';
public const ARCHIVE = 'archive';
public const DELETE = 'delete';
public const START_TOOL_APPLICATION = 'start_tool_application';
public const UPLOAD_FILES = 'upload-files';
public const SHOW_FILES = 'show-files';
/**
* @param string $attribute
* @param mixed $subject
*
* @return bool
*/
protected function supports($attribute, $subject): bool
{
if (!\in_array($attribute, [
self::VIEW,
self::VIEW_TOOL_APPLICATIONS,
self::EDIT,
self::ARCHIVE,
self::DELETE,
self::START_TOOL_APPLICATION,
self::UPLOAD_FILES,
self::SHOW_FILES
], true)) {
return false;
}
if (!$subject instanceof Product) {
return false;
}
return true;
}
/**
* @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 User) {
return false;
}
/** @var Product $product */
$product = $subject;
$hasVotePassed = false;
switch ($attribute) {
case self::VIEW:
$hasVotePassed = $this->canView($product, $user);
break;
case self::VIEW_TOOL_APPLICATIONS:
case self::START_TOOL_APPLICATION:
$hasVotePassed = $this->canStartProductApplication($product, $user);
break;
case self::EDIT:
case self::DELETE:
$hasVotePassed = $this->canEdit($product, $user);
break;
case self::ARCHIVE:
$hasVotePassed = $this->canArchive($product, $user);
break;
case self::UPLOAD_FILES:
$hasVotePassed = $this->canUploadFiles($product, $user);
break;
case self::SHOW_FILES:
$hasVotePassed = $this->canShowFiles($product, $user);
break;
}
return $hasVotePassed;
}
/**
* @param Product $product
* @param User $user
*
* @return bool
*/
private function canView(Product $product, User $user): bool
{
return $user->getOrganization()->getId() === $product->getUser()->getOrganization()->getId();
}
/**
* @param Product $product
* @param User $user
*
* @return bool
*/
private function canStartProductApplication(Product $product, User $user): bool
{
return $this->canView($product, $user) && $product->isActive();
}
/**
* @param Product $product
* @param User $user
*
* @return bool
*/
private function canEdit(Product $product, User $user): bool
{
return ($user->getOrganization()->getId() === $product->getUser()->getOrganization()->getId())
&& (!$product->isDeleted());
}
/**
* @param Product $product
* @param User $user
*
* @return bool
*/
private function canArchive(Product $product, User $user): bool
{
return $this->canEdit($product, $user) && ($product->isActive() || $product->isArchived());
}
/**
* @param Product $product
* @param User $user
*
* @return bool
*/
private function canUploadFiles(Product $product, User $user): bool
{
return ($product->isInUserOrganization($user) || $product->isSystemProduct()) && $product->isActive();
}
/**
* @param Product $product
* @param User $user
*
* @return bool
*/
private function canShowFiles(Product $product, User $user): bool
{
return $product->isInUserOrganization($user) || $product->isSystemProduct();
}
}