SecurityListener::checkGranted()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 7
rs 9.4285
cc 3
eloc 4
nc 2
nop 1
1
<?php
2
3
namespace Pim\Bundle\CustomEntityBundle\EventListener\Action;
4
5
use Oro\Bundle\SecurityBundle\SecurityFacade;
6
use Pim\Bundle\CustomEntityBundle\Action\ActionFactory;
7
use Pim\Bundle\CustomEntityBundle\Event\ActionEvent;
8
use Pim\Bundle\CustomEntityBundle\Event\ActionEvents;
9
use Pim\Bundle\CustomEntityBundle\Event\ConfigurationEvent;
10
use Pim\Bundle\CustomEntityBundle\Event\ConfigurationEvents;
11
use Pim\Bundle\CustomEntityBundle\Event\ConfigureActionEvent;
12
use Pim\Bundle\CustomEntityBundle\Event\PreRenderActionEvent;
13
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
14
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
15
16
/**
17
 * ACL listener for actions
18
 *
19
 * @author    Antoine Guigan <[email protected]>
20
 * @copyright 2013 Akeneo SAS (http://www.akeneo.com)
21
 * @license   http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
22
 */
23
class SecurityListener implements EventSubscriberInterface
24
{
25
    /**
26
     * @var ActionFactory
27
     */
28
    protected $actionFactory;
29
30
    /**
31
     * @var SecurityFacade
32
     */
33
    protected $securityFacade;
34
35
    /**
36
     * @param ActionFactory  $actionFactory
37
     * @param SecurityFacade $securityFacade
38
     */
39
    public function __construct(ActionFactory $actionFactory, SecurityFacade $securityFacade)
40
    {
41
        $this->actionFactory = $actionFactory;
42
        $this->securityFacade = $securityFacade;
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48
    public static function getSubscribedEvents()
49
    {
50
        return [
51
            ConfigurationEvents::CONFIGURE => 'setConfigurationOptions',
52
            ActionEvents::CONFIGURE => 'setDefaultOptions',
53
            ActionEvents::PRE_EXECUTE => 'checkGranted',
54
            ActionEvents::PRE_RENDER => 'removeCreateLink'
55
        ];
56
    }
57
58
    /**
59
     * Adds options to the configuration
60
     *
61
     * @param ConfigurationEvent $event
62
     */
63
    public function setConfigurationOptions(ConfigurationEvent $event)
64
    {
65
        $resolver = $event->getOptionsResolver();
66
        $resolver->setDefined(['acl', 'acl_prefix']);
67
        $resolver->setDefaults(['acl_separator' => '_']);
68
    }
69
70
    /**
71
     * Adds options to the actions
72
     *
73
     * @param ConfigureActionEvent $event
74
     */
75
    public function setDefaultOptions(ConfigureActionEvent $event)
76
    {
77
        $resolver = $event->getOptionsResolver();
78
79
        $options = $event->getAction()->getConfiguration()->getOptions();
80
        if (isset($options['acl'])) {
81
            $resolver->setDefaults(['acl' => $options['acl']]);
82
        } else {
83
            $resolver->setDefined(['acl']);
84
        }
85
        $resolver->setDefined(['acl_suffix']);
86
        $resolver->setNormalizer(
87
            'acl',
88
            function ($actionOptions, $acl) use ($options) {
89
                if (null === $acl && isset($options['acl_prefix']) && isset($actionOptions['acl_suffix'])) {
90
                    return $options['acl_prefix'] . $options['acl_separator'] .
91
                        $actionOptions['acl_suffix'];
92
                }
93
94
                return $acl;
95
            }
96
        );
97
        $customEntityName = $event->getAction()->getConfiguration()->getName();
98
        $normalizeActions = function ($options, $actionTypes) use ($customEntityName) {
99
            return array_filter(
100
                $actionTypes,
101
                function ($actionType) use ($customEntityName) {
102
                    $action = $this->actionFactory->getAction($customEntityName, $actionType);
103
                    $options = $action->getOptions();
104
105
                    return (!isset($options['acl']) || $this->securityFacade->isGranted($options['acl']));
106
                }
107
            );
108
        };
109
        if ('index' === $event->getAction()->getType()) {
110
            $resolver->setNormalizer('row_actions', $normalizeActions);
111
            $resolver->setNormalizer('mass_actions', $normalizeActions);
112
        }
113
    }
114
115
    /**
116
     * Throws an exception if ACL is set and is not granted
117
     *
118
     * @param ActionEvent $event
119
     *
120
     * @throws AccessDeniedHttpException
121
     */
122
    public function checkGranted(ActionEvent $event)
123
    {
124
        $options = $event->getAction()->getOptions();
125
        if (isset($options['acl']) && !$this->securityFacade->isGranted($options['acl'])) {
126
            throw new AccessDeniedHttpException;
127
        }
128
    }
129
130
    /**
131
     * Removes the create link if no ACLS
132
     *
133
     * @param  PreRenderActionEvent $event
134
     * @return type
135
     */
136
    public function removeCreateLink(PreRenderActionEvent $event)
137
    {
138
        $action = $event->getAction();
139
        if ('index' != $action->getType()) {
140
            return;
141
        }
142
143
        $vars = $event->getTemplateVars();
144
        if (!isset($vars['createUrl'])) {
145
            return;
146
        }
147
148
        $customEntityName = $action->getConfiguration()->getName();
149
        $createAction = $this->actionFactory->getAction($customEntityName, 'create');
150
        $options = $createAction->getOptions();
151
        if (isset($options['acl']) && !$this->securityFacade->isGranted($options['acl'])) {
152
            unset($vars['createUrl']);
153
            unset($vars['quickCreate']);
154
            $event->setTemplateVars($vars);
155
        }
156
    }
157
}
158