Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.96% covered (success)
97.96%
48 / 49
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
SwitchUserSubscriber
97.96% covered (success)
97.96%
48 / 49
75.00% covered (warning)
75.00%
3 / 4
11
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getSubscribedEvents
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 supports
100.00% covered (success)
100.00%
20 / 20
100.00% covered (success)
100.00%
1 / 1
6
 onSwitchUser
95.65% covered (success)
95.65%
22 / 23
0.00% covered (danger)
0.00%
0 / 1
3
1<?php
2
3/**
4 * This file is part of the MADIS - RGPD Management application.
5 *
6 * @copyright Copyright (c) 2018-2019 Soluris - Solutions Numériques Territoriales Innovantes
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22declare(strict_types=1);
23
24namespace App\Domain\User\Symfony\EventSubscriber\Kernel;
25
26use App\Domain\Reporting\Dictionary\LogJournalActionDictionary;
27use App\Domain\Reporting\Dictionary\LogJournalSubjectDictionary;
28use App\Domain\Reporting\Model\LogJournal;
29use App\Domain\User\Dictionary\UserRoleDictionary;
30use App\Domain\User\Model\Collectivity;
31use App\Domain\User\Model\User;
32use Doctrine\ORM\EntityManagerInterface;
33use Symfony\Component\EventDispatcher\EventSubscriberInterface;
34use Symfony\Component\Security\Core\Exception\AccessDeniedException;
35use Symfony\Component\Security\Core\Security;
36use Symfony\Component\Security\Http\Event\SwitchUserEvent;
37use Symfony\Component\Security\Http\SecurityEvents;
38
39class SwitchUserSubscriber implements EventSubscriberInterface
40{
41    /**
42     * @var Security
43     */
44    private $security;
45
46    /**
47     * @var EntityManagerInterface
48     */
49    private $entityManager;
50
51    /**
52     * @var \App\Domain\User\Repository\User
53     */
54    private $userRepository;
55
56    public function __construct(
57        Security $security,
58        EntityManagerInterface $em,
59        \App\Domain\User\Repository\User $userRepository,
60    ) {
61        $this->security       = $security;
62        $this->entityManager  = $em;
63        $this->userRepository = $userRepository;
64    }
65
66    public static function getSubscribedEvents()
67    {
68        return [
69            SecurityEvents::SWITCH_USER => 'onSwitchUser',
70        ];
71    }
72
73    private function supports(SwitchUserEvent $event)
74    {
75        $request             = $event->getRequest();
76        $switchUserAttribute = $request->get('_switch_user');
77
78        if ('_exit' === $switchUserAttribute || $this->security->isGranted('ROLE_ADMIN')) {
79            return true;
80        }
81
82        /** @var User $switchUser */
83        $switchUser = $this->userRepository->findOneOrNullByEmail($switchUserAttribute);
84
85        if (\is_null($switchUser)) {
86            return false;
87        }
88
89        $deniedRoles = [UserRoleDictionary::ROLE_REFERENT, UserRoleDictionary::ROLE_ADMIN];
90        if (\in_array($switchUser->getRoles()[0], $deniedRoles)) {
91            return false;
92        }
93
94        /** @var User $connectedUser */
95        $connectedUser  = $this->security->getUser();
96        $collectivities = \array_filter(
97            \iterable_to_array($connectedUser->getCollectivitesReferees()),
98            function (Collectivity $collectivity) use ($switchUser) {
99                return $collectivity === $switchUser->getCollectivity();
100            }
101        );
102
103        if (empty($collectivities)) {
104            return false;
105        }
106
107        return true;
108    }
109
110    public function onSwitchUser(SwitchUserEvent $event)
111    {
112        if (!$this->supports($event)) {
113            throw new AccessDeniedException();
114        }
115
116        $request    = $event->getRequest();
117        $switchUser = $request->get('_switch_user');
118
119        /** @var User $user */
120        $user   = $this->security->getUser();
121        $action = LogJournalActionDictionary::SWITCH_USER_ON;
122        /** @var User $targetUser */
123        $targetUser         = $event->getTargetUser();
124        $switchUserFullName = $targetUser->getFullName();
125
126        if ('_exit' === $switchUser) {
127            $action             = LogJournalActionDictionary::SWITCH_USER_OFF;
128            $switchUserFullName = $user->getFullName();
129            /** @var User $user */
130            $user = $event->getTargetUser();
131        }
132
133        $log = new LogJournal(
134            $user->getCollectivity(),
135            $user->getFullName(),
136            $user->getEmail(),
137            $action,
138            LogJournalSubjectDictionary::USER_USER,
139            $user->getId()->toString(),
140            $switchUserFullName
141        );
142
143        $this->entityManager->persist($log);
144        $this->entityManager->flush();
145    }
146}