src/Security/Voter/Messenger/ConversationMessageVoter.php line 11

Open in your IDE?
  1. <?php
  2. namespace App\Security\Voter\Messenger;
  3. use App\Entity\ConversationMessage;
  4. use App\Security\ApiUser;
  5. use App\Service\User\MemberOperatorService;
  6. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  7. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  8. class ConversationMessageVoter extends Voter
  9. {
  10.     public const DELETE 'delete';
  11.     public const HEART 'heart';
  12.     public const BUY_ATTACHMENT 'buy_attachment';
  13.     public const READ 'read';
  14.     protected function supports(string $attribute$subject): bool
  15.     {
  16.         if (!$subject instanceof ConversationMessage) {
  17.             return false;
  18.         }
  19.         return in_array($attribute, [
  20.             self::DELETE,
  21.             self::READ,
  22.             self::HEART,
  23.             self::BUY_ATTACHMENT,
  24.         ], true);
  25.     }
  26.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  27.     {
  28.         /**
  29.          * @var $user ApiUser
  30.          */
  31.         $user $token->getUser();
  32.         if (!$user instanceof ApiUser) {
  33.             return false;
  34.         }
  35.         switch ($attribute) {
  36.             case self::HEART:
  37.                 return $this->canHeart($subject$user);
  38.             case self::DELETE:
  39.                 return $this->canDelete($subject$user);
  40.             case self::READ:
  41.                 return $this->canRead($subject$user);
  42.             case self::BUY_ATTACHMENT:
  43.                 return $this->canBuyAttachment($subject$user);
  44.         }
  45.         return false;
  46.     }
  47.     protected function canRead(ConversationMessage $messageApiUser $user): bool
  48.     {
  49.         $userMember $user->getMember();
  50.         // gitlab #435
  51.         if ($user->getIsAdmin()) {
  52.             return true;
  53.         }
  54.         // easier to determine
  55.         if ($message->getMember()->getId() === $userMember->getId()) {
  56.             return true;
  57.         }
  58.         foreach ($message->getConversation()->getRoutes() as $route) {
  59.             $from $route->getFromMember();
  60.             if ($from->getId() == $userMember->getId()) {
  61.                 return true;
  62.             }
  63.             if ($user->getIsOperator() && MemberOperatorService::isMemberOperatedByUser($from$user)) {
  64.                 return true;
  65.             }
  66.         }
  67.         return false;
  68.     }
  69.     protected function canDelete(ConversationMessage $messageApiUser $user): bool
  70.     {
  71.         return $message->getMember()->getId() == $user->getMember()->getId();
  72.     }
  73.     protected function canHeart(ConversationMessage $messageApiUser $user): bool
  74.     {
  75.         if (!$this->canRead($message$user)) {
  76.             return false;
  77.         }
  78.         // can only heart a message from someone else, not yourself
  79.         return $message->getMember()->getId() !== $user->getMember()->getId();
  80.     }
  81.     protected function canBuyAttachment(ConversationMessage $messageApiUser $user): bool
  82.     {
  83.         // already bought
  84.         if ($message->getPurchase()) {
  85.             return false;
  86.         }
  87.         // accessor (user) not part of the Conversation
  88.         if (!$this->canRead($message$user)) {
  89.             return false;
  90.         }
  91.         // only, if the sender is not equal to the accessor.
  92.         // so you cant buy attachments for messages you've sent
  93.         return $message->getMember()->getId() !== $user->getMember()->getId();
  94.     }
  95. }