<?php
namespace App\Http\Customer\Voter;
use App\Domain\Transaction\Entity\Transaction;
use App\Domain\Transaction\Repository\CreditHistoryRepository;
use App\Domain\User\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class TransactionVoter extends Voter
{
final public const EDIT_TRANSACTION = 'customer_transaction_edit';
final public const ADD_TRANSACTION = 'customer_transaction_add';
public function __construct(private readonly float $minimumToWithdraw, private readonly CreditHistoryRepository $creditHistoryRepository)
{
}
protected function supports(string $attribute, mixed $subject): bool
{
return match ($attribute) {
self::ADD_TRANSACTION, self::EDIT_TRANSACTION => true,
default => false,
};
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
/** @var ?User $user */
$user = $token->getUser();
if (is_null($user)) {
return false;
}
/* @var Transaction $subject */
return match ($attribute) {
self::EDIT_TRANSACTION => ($user->hasRole('ROLE_ADMIN') || $subject->getUser() === $user) && is_null($subject->getProcessedOn()) && !$subject->isDeleted(),
self::ADD_TRANSACTION => $this->creditHistoryRepository->getBalance($user) >= $this->minimumToWithdraw,
default => true,
};
}
}