1 | <?php |
||||
2 | /* |
||||
3 | * Copyright (C) 2020 Jan Böhmer |
||||
4 | * |
||||
5 | * This program is free software: you can redistribute it and/or modify |
||||
6 | * it under the terms of the GNU Affero General Public License as published |
||||
7 | * by the Free Software Foundation, either version 3 of the License, or |
||||
8 | * (at your option) any later version. |
||||
9 | * |
||||
10 | * This program is distributed in the hope that it will be useful, |
||||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
13 | * GNU Affero General Public License for more details. |
||||
14 | * |
||||
15 | * You should have received a copy of the GNU Affero General Public License |
||||
16 | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
17 | */ |
||||
18 | |||||
19 | namespace App\Audit; |
||||
20 | |||||
21 | use DH\Auditor\Provider\Doctrine\Configuration; |
||||
22 | use DH\Auditor\User\User; |
||||
23 | use DH\Auditor\User\UserInterface as AuditorUserInterface; |
||||
24 | use DH\Auditor\User\UserProviderInterface; |
||||
25 | use Doctrine\Common\EventSubscriber; |
||||
26 | use Doctrine\ORM\Event\PostFlushEventArgs; |
||||
27 | use Doctrine\ORM\Events; |
||||
28 | use Exception; |
||||
29 | use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken; |
||||
30 | use Symfony\Component\Security\Core\Security; |
||||
31 | use Symfony\Component\Security\Core\User\UserInterface; |
||||
32 | |||||
33 | class UserProvider implements UserProviderInterface, EventSubscriber |
||||
34 | { |
||||
35 | public const CLI_USER_IDENTIFER = '$cli'; |
||||
36 | public const INTERNAL_USER_IDENTIFIER = '$internal'; |
||||
37 | |||||
38 | /** |
||||
39 | * @var string|null |
||||
40 | */ |
||||
41 | private $username; |
||||
42 | |||||
43 | /** |
||||
44 | * @var string|null |
||||
45 | */ |
||||
46 | private $identifier; |
||||
47 | |||||
48 | /** |
||||
49 | * @var Security |
||||
50 | */ |
||||
51 | private $security; |
||||
52 | |||||
53 | /** |
||||
54 | * @var Configuration |
||||
55 | */ |
||||
56 | private $configuration; |
||||
57 | |||||
58 | public function __construct(Security $security, Configuration $configuration) |
||||
59 | { |
||||
60 | $this->security = $security; |
||||
61 | $this->configuration = $configuration; |
||||
62 | } |
||||
63 | |||||
64 | public function setManualUsername(?string $username, ?string $identifier): void |
||||
65 | { |
||||
66 | $this->username = $username; |
||||
67 | $this->identifier = $identifier; |
||||
68 | } |
||||
69 | |||||
70 | public function postFlush(PostFlushEventArgs $args): void |
||||
0 ignored issues
–
show
|
|||||
71 | { |
||||
72 | //Reset manual set username and identifier after flush |
||||
73 | $this->username = null; |
||||
74 | $this->identifier = null; |
||||
75 | } |
||||
76 | |||||
77 | public function __invoke(): ?AuditorUserInterface |
||||
78 | { |
||||
79 | $tokenUser = $this->getTokenUser(); |
||||
80 | $impersonatorUser = $this->getImpersonatorUser(); |
||||
81 | |||||
82 | $identifier = null; |
||||
83 | $username = null; |
||||
84 | |||||
85 | if (null !== $tokenUser && $tokenUser instanceof UserInterface) { |
||||
86 | //Use full name of the user if possible |
||||
87 | if ($tokenUser instanceof \App\Entity\User) { |
||||
88 | $identifier = $tokenUser->getUsername(); |
||||
89 | $username = (string) $tokenUser; |
||||
90 | } else { |
||||
91 | if (method_exists($tokenUser, 'getId')) { |
||||
92 | $identifier = $tokenUser->getId(); |
||||
93 | } |
||||
94 | |||||
95 | $username = $tokenUser->getUsername(); |
||||
0 ignored issues
–
show
The function
Symfony\Component\Securi...nterface::getUsername() has been deprecated: since Symfony 5.3, use getUserIdentifier() instead
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
96 | } |
||||
97 | } |
||||
98 | |||||
99 | if (null !== $impersonatorUser && $impersonatorUser instanceof UserInterface) { |
||||
100 | $username .= sprintf('[impersonator %s]', $impersonatorUser->getUsername()); |
||||
0 ignored issues
–
show
The function
Symfony\Component\Securi...nterface::getUsername() has been deprecated: since Symfony 5.3, use getUserIdentifier() instead
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
101 | } |
||||
102 | |||||
103 | //Check if a username and identifier were manually provided |
||||
104 | if (!empty($this->username) && !empty($this->identifier)) { |
||||
105 | $username = $this->username; |
||||
106 | $identifier = $this->identifier; |
||||
107 | } elseif ($this->is_cli()) { //Check if we are on command line, then use the username of the user |
||||
108 | $identifier = self::CLI_USER_IDENTIFER; |
||||
109 | $username = 'CLI'; |
||||
110 | if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) { |
||||
111 | $username = sprintf('CLI [%s]', posix_getpwuid(posix_geteuid())['name']); |
||||
112 | } |
||||
113 | } |
||||
114 | |||||
115 | if (null === $identifier && null === $username) { |
||||
116 | return null; |
||||
117 | } |
||||
118 | |||||
119 | return new User($identifier, $username); |
||||
120 | } |
||||
121 | |||||
122 | private function is_cli(): bool |
||||
123 | { |
||||
124 | if (defined('STDIN')) { |
||||
125 | return true; |
||||
126 | } |
||||
127 | |||||
128 | if ('cli' === php_sapi_name()) { |
||||
129 | return true; |
||||
130 | } |
||||
131 | |||||
132 | if (array_key_exists('SHELL', $_ENV)) { |
||||
133 | return true; |
||||
134 | } |
||||
135 | |||||
136 | if (empty($_SERVER['REMOTE_ADDR']) and !isset($_SERVER['HTTP_USER_AGENT']) and count($_SERVER['argv']) > 0) { |
||||
137 | return true; |
||||
138 | } |
||||
139 | |||||
140 | if (!array_key_exists('REQUEST_METHOD', $_SERVER)) { |
||||
141 | return true; |
||||
142 | } |
||||
143 | |||||
144 | return false; |
||||
145 | } |
||||
146 | |||||
147 | /** |
||||
148 | * @return UserInterface|null |
||||
149 | */ |
||||
150 | private function getTokenUser() |
||||
151 | { |
||||
152 | try { |
||||
153 | $token = $this->security->getToken(); |
||||
154 | } catch (Exception $e) { |
||||
155 | $token = null; |
||||
156 | } |
||||
157 | |||||
158 | if (null === $token) { |
||||
159 | return null; |
||||
160 | } |
||||
161 | |||||
162 | $tokenUser = $token->getUser(); |
||||
163 | if ($tokenUser instanceof UserInterface) { |
||||
164 | return $tokenUser; |
||||
165 | } |
||||
166 | |||||
167 | return null; |
||||
168 | } |
||||
169 | |||||
170 | /** |
||||
171 | * @return string|UserInterface|null |
||||
172 | */ |
||||
173 | private function getImpersonatorUser() |
||||
174 | { |
||||
175 | $token = $this->security->getToken(); |
||||
176 | |||||
177 | // Symfony >= 5 |
||||
178 | if (class_exists(SwitchUserToken::class) && $token instanceof SwitchUserToken) { |
||||
179 | return $token->getOriginalToken() |
||||
180 | ->getUser(); |
||||
181 | } |
||||
182 | |||||
183 | return null; |
||||
184 | } |
||||
185 | |||||
186 | public function getSubscribedEvents() |
||||
187 | { |
||||
188 | return [ |
||||
189 | Events::postFlush, |
||||
190 | ]; |
||||
191 | } |
||||
192 | } |
||||
193 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.