src/Security/SmsVoter.php line 45

Open in your IDE?
  1. <?php
  2. //------------------------------------------------------------------------------
  3. // src/Security/SmsVoter.php
  4. //------------------------------------------------------------------------------
  5. namespace App\Security;
  6. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  7. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  8. use Doctrine\Persistence\ManagerRegistry;
  9. use App\Entity\Access;
  10. use App\Entity\Client\Client;
  11. use App\Entity\Config\Config;
  12. use App\Entity\Communication\Sms\SmsPhoneNumber;
  13. use App\Entity\Config\Module;
  14. use App\Entity\HR\AccessFunction;
  15. use App\Entity\HR\HumanResource;
  16. use App\Entity\Security\Acl;
  17. use App\Entity\Security\AclPermission;
  18. use App\Entity\SocietyGroup;
  19. use App\Services\Communication\SmsTools;
  20. use App\Services\Config\ModuleTools;
  21. class SmsVoter extends Voter
  22. {
  23.     //--------------------------------------------------------------------------------
  24.     // is_granted constants
  25.     const IS_ACTIVE "sms_is_active";
  26.     const NUMBER_ASSIGNED "sms_number_is_assigned";
  27.     const CAN_SEND "can_send_sms";
  28.     const IS_GRANTED_CONSTANTS = array(
  29.         self::IS_ACTIVE,
  30.         self::NUMBER_ASSIGNED,
  31.         self::CAN_SEND,
  32.     );
  33.     public function __construct(ManagerRegistry $doctrineModuleTools $moduleToolsSmsTools $smsTools)
  34.     {
  35.         $this->em $doctrine->getManager();
  36.         $this->moduleTools $moduleTools;
  37.         $this->smsTools $smsTools;
  38.         $this->aclRepository $this->em->getRepository(Acl::class);
  39.         $this->aclPermissionRepository $this->em->getRepository(AclPermission::class);
  40.     }
  41.     // Plan.io Task #4453 [See AccessVoter for details]
  42.     public function supportsAttribute(string $attribute): bool
  43.     {
  44.         return in_array($attributeself::IS_GRANTED_CONSTANTStrue);
  45.     }
  46.     protected function supports(string $attribute$subject null): bool
  47.     {
  48.         // if the attribute isn't one we support, return false
  49.         if (!in_array($attributeself::IS_GRANTED_CONSTANTS))
  50.         {
  51.             return false;
  52.         }
  53.         // only vote on Client objects inside this voter
  54.         if ($subject !== null && !$subject instanceof Client && !$subject instanceof HumanResource)
  55.         {
  56.             return false;
  57.         }
  58.         return true;
  59.     }
  60.     protected function voteOnAttribute(string $attribute$subjectTokenInterface $token): bool
  61.     {
  62.         $user $token->getUser();
  63.         if (!$user instanceof Access)
  64.         {
  65.             // the user must be logged in; if not, deny access
  66.             return false;
  67.         }
  68.         // The user must have a function; if not deny access
  69.         $function $user->getFunction();
  70.         if ($function === null)        return false;
  71.         // Plan.io Task #3710 : Get current group
  72.         $currentGroup $user->getSocietyGroup();
  73.         if ($currentGroup === null)
  74.             return false;
  75.         $this->currentGroup $currentGroup;
  76.         // Module activated ?
  77.         if ($this->moduleTools->isInactiveByCode($currentGroupModule::MODULE_SMS))
  78.         {
  79.             return false;
  80.         }
  81.         // Check current group affectation
  82.         if ($subject !== null)
  83.         {
  84.             $subjectSociety $subject->getSociety();
  85.             if ($subjectSociety === null)
  86.             {
  87.                 return false;
  88.             }
  89.             $subjectGroup $subjectSociety->getGroup();
  90.             if ($subjectGroup === null)
  91.             {
  92.                 return false;
  93.             }
  94.             if (!$currentGroup->equals($subjectGroup))
  95.             {
  96.                 // Classic case
  97.                 if ($subject instanceof Client === false)
  98.                 {
  99.                     return false;
  100.                 }
  101.                 // Task plan.io #4313 - Allow send sms for "shared" Client
  102.                 if ($subject->hasMissionOwnedBySocietyGroup($this->currentGroup) === false)
  103.                 {
  104.                     return false;
  105.                 }
  106.             }
  107.         }
  108.         switch ($attribute)
  109.         {
  110.             // Check is done before, in the voteOnAttribute
  111.             case self::IS_ACTIVE:
  112.                 return true;
  113.             case self::NUMBER_ASSIGNED:
  114.                 return $this->numberAssigned($currentGroup$user$function);
  115.             case self::CAN_SEND:
  116.                 return $this->canSend($subject$user$function);
  117.         }
  118.         throw new \LogicException('This code should not be reached!');
  119.     }
  120.     private function numberAssigned(SocietyGroup $societyGroupAccess $userAccessFunction $function)
  121.     {
  122.         // Plan.io Task #3980
  123.         // This handles both cases : SmsMode and TwilioSms
  124.         $smsPhoneNumber $this->smsTools->getPhoneNumberForSocietyGroup($societyGroup);
  125.         if ($smsPhoneNumber === null)
  126.         {
  127.             return false;
  128.         }
  129.         return true;
  130.     }
  131.     // Updated by Plan.io Task #4515
  132.     private function canSend($recipientAccess $userAccessFunction $function)
  133.     {
  134.         // Check if recipient has a valid phone
  135.         if ($recipient instanceof Client)
  136.         {
  137.             $individual $recipient->getIndividual();
  138.             $validPhoneObjectList $this->smsTools->getIndividualPhonesForSms($individual);
  139.             if (count($validPhoneObjectList) < 1)
  140.             {
  141.                 return false;
  142.             }
  143.         }
  144.         else if ($recipient instanceof HumanResource)
  145.         {
  146.             $phoneFormatted $this->smsTools->phoneFormat($recipient->getPhone());
  147.             if ($phoneFormatted === null)
  148.             {
  149.                 return false;
  150.             }
  151.         }
  152.         else
  153.         {
  154.             // Default case
  155.             return false;
  156.         }        
  157.         // Does the society group have a phone number ?
  158.         // Plan.io Task #3980
  159.         // This handles both cases : SmsMode and TwilioSms
  160.         // Plan.io Task #4313 : <!> Don't use the client SocietyGroup
  161.         $smsPhoneNumber $this->smsTools->getPhoneNumberForSocietyGroup($this->currentGroup);
  162.         if ($smsPhoneNumber === null)
  163.         {
  164.             return false;
  165.         }
  166.         // All looks good
  167.         return true;
  168.     }
  169. }