src/Security/AccessVoter.php line 11

Open in your IDE?
  1. <?php
  2. namespace App\Security;
  3. use App\DBAL\Types\AccessRoleType;
  4. use App\Entity;
  5. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  6. use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
  7. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  8. class AccessVoter extends Voter
  9. {
  10.     public const SYSTEM_ADMIN 'SYSTEM_ADMIN';
  11.     public const DATA_EXPORT 'DATA_EXPORT';
  12.     public const VIEW_REPORTS 'VIEW_REPORTS';
  13.     public const VIEW_WIDGETS 'VIEW_WIDGETS';
  14.     public const ACTION_CREATE 'ACTION_CREATE';
  15.     public const ACTION_EDIT 'ACTION_EDIT';
  16.     public const ACTION_DELETE 'ACTION_DELETE';
  17.     public const VIEW_OPPORTUNITIES 'VIEW_OPPORTUNITIES';
  18.     public const OBJECT_USER 'OBJECT_USER';
  19.     public const OBJECT_CHAT 'OBJECT_CHAT';
  20.     public const OBJECT_FILTER 'OBJECT_FILTER';
  21.     public const OBJECT_LEAD 'OBJECT_LEAD';
  22.     public const OBJECT_LEAD_COMMENT 'OBJECT_LEAD_COMMENT';
  23.     public const OBJECT_CUSTOMER 'OBJECT_CUSTOMER';
  24.     public const OBJECT_CUSTOMER_INTERVIEW_FORM 'OBJECT_CUSTOMER_INTERVIEW_FORM';
  25.     public const OBJECT_CUSTOMER_INTERVIEW_NOTE 'OBJECT_CUSTOMER_INTERVIEW_NOTE';
  26.     public const OBJECT_CUSTOMER_GOAL_TIME 'OBJECT_CUSTOMER_GOAL_TIME';
  27.     public const OBJECT_CUSTOMER_INVOICE 'OBJECT_CUSTOMER_INVOICE';
  28.     public const OBJECT_CUSTOMER_TRANSACTION 'OBJECT_CUSTOMER_TRANSACTION';
  29.     public const OBJECT_CUSTOMER_MESSAGE 'OBJECT_CUSTOMER_MESSAGE';
  30.     public const OBJECT_CUSTOMER_LETTER 'OBJECT_CUSTOMER_LETTER';
  31.     public const OBJECT_CUSTOMER_FILE 'OBJECT_CUSTOMER_FILE';
  32.     public const OBJECT_CUSTOMER_EVENT 'OBJECT_CUSTOMER_EVENT';
  33.     public const OBJECT_CUSTOMER_EVENT_COMMENT 'OBJECT_CUSTOMER_EVENT_COMMENT';
  34.     public const OBJECT_CUSTOMER_COMPLAINT 'OBJECT_CUSTOMER_COMPLAINT';
  35.     public const OBJECT_CUSTOMER_COMPLAINT_COMMENT 'OBJECT_CUSTOMER_COMPLAINT_COMMENT';
  36.     public const OBJECT_CUSTOMER_UPSELL_REQUEST 'OBJECT_CUSTOMER_UPSELL_REQUEST';
  37.     public const OBJECT_CUSTOMER_UPSELL_REQUEST_COMMENT 'OBJECT_CUSTOMER_UPSELL_REQUEST_COMMENT';
  38.     public const OBJECT_CUSTOMER_TAX_RETURN 'OBJECT_CUSTOMER_TAX_RETURN';
  39.     public const OBJECT_CUSTOMER_TAX_RETURN_COMMENT 'OBJECT_CUSTOMER_TAX_RETURN_COMMENT';
  40.     public const OBJECT_CUSTOMER_STATUS_LOG 'OBJECT_CUSTOMER_STATUS_LOG';
  41.     public const OBJECT_CUSTOMER_RATING_LOG 'OBJECT_CUSTOMER_RATING_LOG';
  42.     public const OBJECT_CUSTOMER_REQUEST 'OBJECT_CUSTOMER_REQUEST';
  43.     public const OBJECT_EVENT 'OBJECT_EVENT';
  44.     public const OBJECT_EVENT_COMMENT 'OBJECT_EVENT_COMMENT';
  45.     public const OBJECT_PROJECT 'OBJECT_PROJECT';
  46.     public const OBJECT_PROJECT_CARD 'OBJECT_PROJECT_CARD';
  47.     public const OBJECT_PROJECT_ITEM 'OBJECT_PROJECT_ITEM';
  48.     public const OBJECT_PROJECT_COMMENT 'OBJECT_PROJECT_COMMENT';
  49.     public const OBJECT_PROJECT_WHITEBOARD 'OBJECT_PROJECT_WHITEBOARD';
  50.     public const OBJECT_FEED 'OBJECT_FEED';
  51.     public const OBJECT_FEED_OPTION 'OBJECT_FEED_OPTION';
  52.     public const OBJECT_FEED_COMMENT 'OBJECT_FEED_COMMENT';
  53.     public const OBJECT_ISSUE 'OBJECT_ISSUE';
  54.     public const OBJECT_ISSUE_COMMENT 'OBJECT_ISSUE_COMMENT';
  55.     public const OBJECT_STREAM 'OBJECT_STREAM';
  56.     public const OBJECT_STREAM_COMMENT 'OBJECT_STREAM_COMMENT';
  57.     public const OBJECT_MESSAGE 'OBJECT_MESSAGE';
  58.     public const OBJECT_NOTIFICATION 'OBJECT_NOTIFICATION';
  59.     public const OBJECT_REPORT 'OBJECT_REPORT';
  60.     public const OBJECT_WIDGET 'OBJECT_WIDGET';
  61.     /** @var AccessDecisionManagerInterface */
  62.     private $decisionManager;
  63.     /**
  64.      * @param AccessDecisionManagerInterface $decisionManager
  65.      */
  66.     public function __construct(AccessDecisionManagerInterface $decisionManager)
  67.     {
  68.         $this->decisionManager $decisionManager;
  69.     }
  70.     /**
  71.      * {@inheritdoc}
  72.      */
  73.     protected function supports($attribute$subject)
  74.     {
  75.         list($attribute) = explode('|'$attribute);
  76.         // if the attribute isn't one we support, return false
  77.         if (!\in_array($attribute, [
  78.             self::SYSTEM_ADMIN,
  79.             self::DATA_EXPORT,
  80.             self::VIEW_REPORTS,
  81.             self::VIEW_WIDGETS,
  82.             self::OBJECT_USER,
  83.             self::OBJECT_CHAT,
  84.             self::OBJECT_FILTER,
  85.             self::OBJECT_LEAD,
  86.             self::OBJECT_LEAD_COMMENT,
  87.             self::OBJECT_CUSTOMER,
  88.             self::OBJECT_CUSTOMER_INTERVIEW_FORM,
  89.             self::OBJECT_CUSTOMER_INTERVIEW_NOTE,
  90.             self::OBJECT_CUSTOMER_GOAL_TIME,
  91.             self::OBJECT_CUSTOMER_INVOICE,
  92.             self::OBJECT_CUSTOMER_TRANSACTION,
  93.             self::OBJECT_CUSTOMER_MESSAGE,
  94.             self::OBJECT_CUSTOMER_LETTER,
  95.             self::OBJECT_CUSTOMER_FILE,
  96.             self::OBJECT_CUSTOMER_EVENT,
  97.             self::OBJECT_CUSTOMER_EVENT_COMMENT,
  98.             self::OBJECT_CUSTOMER_UPSELL_REQUEST,
  99.             self::OBJECT_CUSTOMER_UPSELL_REQUEST_COMMENT,
  100.             self::OBJECT_CUSTOMER_TAX_RETURN,
  101.             self::OBJECT_CUSTOMER_TAX_RETURN_COMMENT,
  102.             self::OBJECT_CUSTOMER_COMPLAINT,
  103.             self::OBJECT_CUSTOMER_COMPLAINT_COMMENT,
  104.             self::OBJECT_CUSTOMER_STATUS_LOG,
  105.             self::OBJECT_CUSTOMER_RATING_LOG,
  106.             self::OBJECT_CUSTOMER_REQUEST,
  107.             self::OBJECT_EVENT,
  108.             self::OBJECT_EVENT_COMMENT,
  109.             self::OBJECT_PROJECT,
  110.             self::OBJECT_PROJECT_CARD,
  111.             self::OBJECT_PROJECT_ITEM,
  112.             self::OBJECT_PROJECT_COMMENT,
  113.             self::OBJECT_PROJECT_WHITEBOARD,
  114.             self::OBJECT_FEED,
  115.             self::OBJECT_FEED_OPTION,
  116.             self::OBJECT_FEED_COMMENT,
  117.             self::OBJECT_ISSUE,
  118.             self::OBJECT_ISSUE_COMMENT,
  119.             self::OBJECT_STREAM,
  120.             self::OBJECT_STREAM_COMMENT,
  121.             self::OBJECT_MESSAGE,
  122.             self::OBJECT_NOTIFICATION,
  123.             self::OBJECT_REPORT,
  124.             self::OBJECT_WIDGET,
  125.         ])) {
  126.             return false;
  127.         }
  128.         // only vote on X objects inside this voter
  129.         if (!(!$subject
  130.             || (self::OBJECT_USER === $attribute && $subject instanceof Entity\User)
  131.             || (self::OBJECT_CHAT === $attribute && $subject instanceof Entity\Chat\Chat)
  132.             || (self::OBJECT_FILTER === $attribute && $subject instanceof Entity\Filter)
  133.             || (self::OBJECT_LEAD === $attribute && $subject instanceof Entity\Lead\Lead)
  134.             || (self::OBJECT_LEAD_COMMENT === $attribute && $subject instanceof Entity\Lead\Comment)
  135.             || (self::OBJECT_CUSTOMER === $attribute && $subject instanceof Entity\Customer\Customer)
  136.             || (self::OBJECT_CUSTOMER_INTERVIEW_FORM === $attribute && $subject instanceof Entity\Customer\InterviewForm)
  137.             || (self::OBJECT_CUSTOMER_INTERVIEW_NOTE === $attribute && $subject instanceof Entity\Customer\InterviewNote)
  138.             || (self::OBJECT_CUSTOMER_GOAL_TIME === $attribute && $subject instanceof Entity\Customer\GoalTime)
  139.             || (self::OBJECT_CUSTOMER_INVOICE === $attribute && $subject instanceof Entity\Customer\Invoice)
  140.             || (self::OBJECT_CUSTOMER_TRANSACTION === $attribute && $subject instanceof Entity\Customer\Transaction)
  141.             || (\in_array($attribute, [self::OBJECT_MESSAGEself::OBJECT_CUSTOMER_MESSAGE]) && $subject instanceof Entity\Customer\Message)
  142.             || (self::OBJECT_CUSTOMER_LETTER === $attribute && $subject instanceof Entity\Customer\Letter)
  143.             || (self::OBJECT_CUSTOMER_FILE === $attribute && $subject instanceof Entity\Customer\File)
  144.             || (self::OBJECT_CUSTOMER_COMPLAINT === $attribute && $subject instanceof Entity\Customer\Complaint)
  145.             || (self::OBJECT_CUSTOMER_COMPLAINT_COMMENT === $attribute && $subject instanceof Entity\Customer\Comment\ComplaintComment)
  146.             || (self::OBJECT_CUSTOMER_UPSELL_REQUEST === $attribute && $subject instanceof Entity\Customer\UpsellRequest)
  147.             || (self::OBJECT_CUSTOMER_UPSELL_REQUEST_COMMENT === $attribute && $subject instanceof Entity\Customer\Comment\UpsellRequestComment)
  148.             || (self::OBJECT_CUSTOMER_TAX_RETURN === $attribute && $subject instanceof Entity\Customer\TaxReturn)
  149.             || (self::OBJECT_CUSTOMER_TAX_RETURN_COMMENT === $attribute && $subject instanceof Entity\Customer\Comment\TaxReturnComment)
  150.             || (self::OBJECT_CUSTOMER_STATUS_LOG === $attribute && $subject instanceof Entity\Customer\StatusLog)
  151.             || (self::OBJECT_CUSTOMER_RATING_LOG === $attribute && $subject instanceof Entity\Customer\RatingLog)
  152.             || (self::OBJECT_CUSTOMER_REQUEST === $attribute && $subject instanceof Entity\Customer\Request)
  153.             || (\in_array($attribute, [self::OBJECT_EVENTself::OBJECT_CUSTOMER_EVENT]) && $subject instanceof Entity\Event\Event)
  154.             || (\in_array($attribute, [self::OBJECT_EVENT_COMMENTself::OBJECT_CUSTOMER_EVENT_COMMENT]) && $subject instanceof Entity\Event\Comment)
  155.             || (self::OBJECT_PROJECT === $attribute && $subject instanceof Entity\Project\Project)
  156.             || (self::OBJECT_PROJECT_CARD === $attribute && $subject instanceof Entity\Project\Card)
  157.             || (self::OBJECT_PROJECT_ITEM === $attribute && $subject instanceof Entity\Project\Item)
  158.             || (self::OBJECT_PROJECT_COMMENT === $attribute && $subject instanceof Entity\Project\Comment)
  159.             || (self::OBJECT_PROJECT_WHITEBOARD === $attribute && $subject instanceof Entity\Project\Whiteboard)
  160.             || (self::OBJECT_FEED === $attribute && $subject instanceof Entity\Feed\Feed)
  161.             || (self::OBJECT_FEED_OPTION === $attribute && $subject instanceof Entity\Feed\Option)
  162.             || (self::OBJECT_FEED_COMMENT === $attribute && $subject instanceof Entity\Feed\Comment)
  163.             || (self::OBJECT_ISSUE === $attribute && $subject instanceof Entity\Issue\Issue)
  164.             || (self::OBJECT_ISSUE_COMMENT === $attribute && $subject instanceof Entity\Issue\Comment)
  165.             || (self::OBJECT_STREAM === $attribute && $subject instanceof Entity\Stream\Stream)
  166.             || (self::OBJECT_STREAM_COMMENT === $attribute && $subject instanceof Entity\Stream\Comment)
  167.             || (self::OBJECT_NOTIFICATION === $attribute && $subject instanceof Entity\Notification)
  168.             || (self::OBJECT_REPORT === $attribute && $subject instanceof Entity\Report)
  169.             || (self::OBJECT_WIDGET === $attribute && $subject instanceof Entity\Widget)
  170.         )) {
  171.             return false;
  172.         }
  173.         return true;
  174.     }
  175.     /**
  176.      * {@inheritdoc}
  177.      */
  178.     protected function voteOnAttribute($attribute$subjectTokenInterface $token)
  179.     {
  180.         $tmp explode('|'$attribute);
  181.         $attribute $tmp[0];
  182.         $action $tmp[1] ?? null;
  183.         switch ($action) {
  184.             case self::ACTION_CREATE:
  185.                 $action AccessRoleType::CREATE;
  186.                 break;
  187.             case self::ACTION_EDIT:
  188.                 $action AccessRoleType::EDIT;
  189.                 break;
  190.             case self::ACTION_DELETE:
  191.                 $action AccessRoleType::DELETE;
  192.                 break;
  193.             case self::VIEW_OPPORTUNITIES:
  194.                 break;
  195.             default:
  196.                 $action null;
  197.         }
  198.         $user $token->getUser();
  199.         // the user must be logged in; if not, deny access
  200.         if (!$user instanceof Entity\User) {
  201.             return false;
  202.         }
  203.         // ROLE_ADMIN can do anything!
  204.         if ($this->decisionManager->decide($token, ['ROLE_ADMIN']) || $user->isAllowSystemAdmin()) {
  205.             return true;
  206.         }
  207.         if (self::DATA_EXPORT === $attribute && $user->isAllowDataExport()) {
  208.             return true;
  209.         }
  210.         if (self::VIEW_REPORTS === $attribute && $user->hasAccessToReport()) {
  211.             return true;
  212.         }
  213.         if (self::VIEW_WIDGETS === $attribute/*  && $user->hasAccessToWidget() */) {
  214.             return true;
  215.         }
  216.         // you can only perform self actions
  217.         if (self::OBJECT_USER === $attribute
  218.             && $subject instanceof User
  219.             && $subject->getId() === $user->getId()
  220.         ) {
  221.             return true;
  222.         }
  223.         // check access via team
  224.         if (!$subject
  225.             && \in_array($attribute, [
  226.                 self::OBJECT_LEAD,
  227.                 self::OBJECT_CUSTOMER,
  228.                 self::OBJECT_EVENT,
  229.                 self::OBJECT_PROJECT,
  230.                 self::OBJECT_FEED,
  231.                 self::OBJECT_ISSUE,
  232.                 self::OBJECT_STREAM,
  233.                 self::OBJECT_MESSAGE,
  234.             ])
  235.             && $user->hasEntityAccess(substr(strtolower($attribute), 7), $action)
  236.         ) {
  237.             return true;
  238.         }
  239.         if (!$subject
  240.             && \in_array($attribute, [
  241.                 self::OBJECT_CUSTOMER_INTERVIEW_FORM,
  242.                 self::OBJECT_CUSTOMER_INTERVIEW_NOTE,
  243.                 self::OBJECT_CUSTOMER_GOAL_TIME,
  244.                 self::OBJECT_CUSTOMER_INVOICE,
  245.                 self::OBJECT_CUSTOMER_TRANSACTION,
  246.                 self::OBJECT_CUSTOMER_MESSAGE,
  247.                 self::OBJECT_CUSTOMER_LETTER,
  248.                 self::OBJECT_CUSTOMER_FILE,
  249.                 self::OBJECT_CUSTOMER_EVENT,
  250.                 self::OBJECT_CUSTOMER_EVENT_COMMENT,
  251.                 self::OBJECT_CUSTOMER_UPSELL_REQUEST,
  252.                 self::OBJECT_CUSTOMER_UPSELL_REQUEST_COMMENT,
  253.                 self::OBJECT_CUSTOMER_TAX_RETURN,
  254.                 self::OBJECT_CUSTOMER_TAX_RETURN_COMMENT,
  255.                 self::OBJECT_CUSTOMER_COMPLAINT,
  256.                 self::OBJECT_CUSTOMER_COMPLAINT_COMMENT,
  257.                 self::OBJECT_CUSTOMER_STATUS_LOG,
  258.                 self::OBJECT_CUSTOMER_RATING_LOG,
  259.                 self::OBJECT_CUSTOMER_REQUEST,
  260.             ])
  261.             && $user->hasEntityAccess(substr(strtolower(self::OBJECT_CUSTOMER), 7), AccessRoleType::EDIT)
  262.         ) {
  263.             return true;
  264.         }
  265.         if ($subject) {
  266.             // reject subjects connected to other users
  267.             if (\in_array($attribute, [
  268.                 self::OBJECT_FILTER,
  269.                 self::OBJECT_NOTIFICATION,
  270.             ]) && (!$subject->getUser()
  271.                 || $subject->getUser()->getId() !== $user->getId()
  272.             )) {
  273.                 return false;
  274.             }
  275.             // allow non-configured permission subjects
  276.             if (\in_array($attribute, [
  277.                 self::OBJECT_FILTER,
  278.                 self::OBJECT_NOTIFICATION,
  279.             ])) {
  280.                 return true;
  281.             }
  282.             // access to chat
  283.             if (self::OBJECT_CHAT === $attribute) {
  284.                 return $subject->hasParticipantByUser($user);
  285.             }
  286.             // access to reports
  287.             if (self::OBJECT_REPORT === $attribute) {
  288.                 return $user->hasAccessToReport($subject);
  289.             }
  290.             // access to widgets
  291.             if (self::OBJECT_WIDGET === $attribute) {
  292.                 return $user->hasAccessToWidget($subject);
  293.             }
  294.             // no user asigned
  295.             if (!method_exists($subject'getUser') || !$creator $subject->getUser()) {
  296.                 return true;
  297.             }
  298.             /*
  299.             // creator is me
  300.             if ($user->getId() === $creator->getId()) {
  301.                 return true;
  302.             }
  303.             */
  304.             if (\in_array($attribute, [
  305.                 self::OBJECT_LEAD_COMMENT,
  306.                 self::OBJECT_EVENT_COMMENT,
  307.                 self::OBJECT_PROJECT_COMMENT,
  308.                 self::OBJECT_FEED_COMMENT,
  309.                 self::OBJECT_ISSUE_COMMENT,
  310.                 self::OBJECT_STREAM_COMMENT,
  311.             ])) {
  312.                 $attribute substr($attribute0, -8);
  313.             }
  314.             if (\in_array($attribute, [
  315.                 self::OBJECT_PROJECT_CARD,
  316.                 self::OBJECT_PROJECT_ITEM,
  317.             ])) {
  318.                 $attribute substr($attribute0, -5);
  319.             }
  320.             if (\in_array($attribute, [
  321.                 self::OBJECT_PROJECT_WHITEBOARD,
  322.             ])) {
  323.                 $attribute substr($attribute0, -12);
  324.             }
  325.             if (\in_array($attribute, [
  326.                 self::OBJECT_FEED_OPTION,
  327.             ])) {
  328.                 $attribute substr($attribute0, -7);
  329.             }
  330.             if (\in_array($attribute, [
  331.                 self::OBJECT_CUSTOMER_INTERVIEW_FORM,
  332.                 self::OBJECT_CUSTOMER_INTERVIEW_NOTE,
  333.                 self::OBJECT_CUSTOMER_GOAL_TIME,
  334.                 self::OBJECT_CUSTOMER_INVOICE,
  335.                 self::OBJECT_CUSTOMER_TRANSACTION,
  336.                 self::OBJECT_CUSTOMER_MESSAGE,
  337.                 self::OBJECT_CUSTOMER_LETTER,
  338.                 self::OBJECT_CUSTOMER_FILE,
  339.                 self::OBJECT_CUSTOMER_EVENT,
  340.                 self::OBJECT_CUSTOMER_EVENT_COMMENT,
  341.                 self::OBJECT_CUSTOMER_UPSELL_REQUEST,
  342.                 self::OBJECT_CUSTOMER_UPSELL_REQUEST_COMMENT,
  343.                 self::OBJECT_CUSTOMER_TAX_RETURN,
  344.                 self::OBJECT_CUSTOMER_TAX_RETURN_COMMENT,
  345.                 self::OBJECT_CUSTOMER_COMPLAINT,
  346.                 self::OBJECT_CUSTOMER_COMPLAINT_COMMENT,
  347.                 self::OBJECT_CUSTOMER_STATUS_LOG,
  348.                 self::OBJECT_CUSTOMER_RATING_LOG,
  349.                 self::OBJECT_CUSTOMER_REQUEST,
  350.             ])) {
  351.                 $attribute self::OBJECT_CUSTOMER;
  352.                 if (AccessRoleType::DELETE === $action) {
  353.                     $action AccessRoleType::EDIT;
  354.                 }
  355.             }
  356.             // access to record
  357.             if ($user->hasEntityAccess(substr(strtolower($attribute), 7), $action)) {
  358.                 return true;
  359.             }
  360.         }
  361.         return false;
  362.     }
  363. }