1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Copyright 2014 SURFnet bv |
5
|
|
|
* |
6
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
7
|
|
|
* you may not use this file except in compliance with the License. |
8
|
|
|
* You may obtain a copy of the License at |
9
|
|
|
* |
10
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0 |
11
|
|
|
* |
12
|
|
|
* Unless required by applicable law or agreed to in writing, software |
13
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, |
14
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15
|
|
|
* See the License for the specific language governing permissions and |
16
|
|
|
* limitations under the License. |
17
|
|
|
*/ |
18
|
|
|
|
19
|
|
|
namespace Surfnet\StepupRa\RaBundle\Controller; |
20
|
|
|
|
21
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; |
22
|
|
|
use Surfnet\StepupRa\RaBundle\Command\ExportRaSecondFactorsCommand; |
23
|
|
|
use Surfnet\StepupRa\RaBundle\Command\RevokeSecondFactorCommand; |
24
|
|
|
use Surfnet\StepupRa\RaBundle\Command\SearchRaSecondFactorsCommand; |
25
|
|
|
use Surfnet\StepupRa\RaBundle\Command\SearchSecondFactorAuditLogCommand; |
26
|
|
|
use Surfnet\StepupRa\RaBundle\Form\Type\RevokeSecondFactorType; |
27
|
|
|
use Surfnet\StepupRa\RaBundle\Form\Type\SearchRaSecondFactorsType; |
28
|
|
|
use Surfnet\StepupRa\RaBundle\Service\InstitutionConfigurationOptionsService; |
29
|
|
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
30
|
|
|
use Symfony\Component\HttpFoundation\Request; |
31
|
|
|
use Symfony\Component\HttpFoundation\Response; |
32
|
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) By making the Form Type classes explicit, MD now realizes couping |
36
|
|
|
* is to high. |
37
|
|
|
*/ |
38
|
|
|
final class SecondFactorController extends Controller |
39
|
|
|
{ |
40
|
|
|
/** |
41
|
|
|
* @Template |
42
|
|
|
* @param Request $request |
43
|
|
|
* @return array|Response |
44
|
|
|
*/ |
45
|
|
|
public function searchAction(Request $request) |
46
|
|
|
{ |
47
|
|
|
$this->denyAccessUnlessGranted(['ROLE_RA']); |
48
|
|
|
|
49
|
|
|
$identity = $this->getCurrentUser(); |
50
|
|
|
$this->get('logger')->notice('Starting search for second factors'); |
51
|
|
|
|
52
|
|
|
$institutionFilterOptions = $this |
53
|
|
|
->getInstitutionConfigurationOptionsService() |
54
|
|
|
->getAvailableInstitutionsFor($identity->institution); |
55
|
|
|
|
56
|
|
|
$command = new SearchRaSecondFactorsCommand(); |
57
|
|
|
$command->actorInstitution = $identity->institution; |
58
|
|
|
$command->pageNumber = (int) $request->get('p', 1); |
59
|
|
|
$command->orderBy = $request->get('orderBy'); |
60
|
|
|
$command->orderDirection = $request->get('orderDirection'); |
61
|
|
|
|
62
|
|
|
// The options that will populate the institution filter choice list. |
63
|
|
|
$command->institutionFilterOptions = $institutionFilterOptions; |
64
|
|
|
|
65
|
|
|
$form = $this->createForm(SearchRaSecondFactorsType::class, $command, ['method' => 'get']); |
66
|
|
|
$form->handleRequest($request); |
67
|
|
|
|
68
|
|
|
$secondFactors = $this->getSecondFactorService()->search($command); |
69
|
|
|
$secondFactorCount = $secondFactors->getTotalItems(); |
70
|
|
|
|
71
|
|
|
if ($form->isSubmitted() && $form->getClickedButton()->getName() == 'export') { |
72
|
|
|
$this->get('logger')->notice('Forwarding to export second factors action'); |
73
|
|
|
return $this->forward('SurfnetStepupRaRaBundle:SecondFactor:export', ['command' => $command]); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
$pagination = $this->get('knp_paginator')->paginate( |
77
|
|
|
$secondFactors->getElements(), |
78
|
|
|
$secondFactors->getCurrentPage(), |
79
|
|
|
$secondFactors->getItemsPerPage() |
80
|
|
|
); |
81
|
|
|
|
82
|
|
|
$revocationForm = $this->createForm(RevokeSecondFactorType::class, new RevokeSecondFactorCommand()); |
83
|
|
|
|
84
|
|
|
$this->get('logger')->notice(sprintf( |
85
|
|
|
'Searching for second factors yielded "%d" results', |
86
|
|
|
$secondFactors->getTotalItems() |
87
|
|
|
)); |
88
|
|
|
|
89
|
|
|
return [ |
90
|
|
|
'form' => $form->createView(), |
91
|
|
|
'revocationForm' => $revocationForm->createView(), |
92
|
|
|
'secondFactors' => $secondFactors, |
93
|
|
|
'pagination' => $pagination, |
94
|
|
|
'numberOfSecondFactors' => $secondFactorCount, |
95
|
|
|
'orderBy' => $command->orderBy, |
96
|
|
|
'orderDirection' => $command->orderDirection ?: 'asc', |
97
|
|
|
'inverseOrderDirection' => $command->orderDirection === 'asc' ? 'desc' : 'asc', |
98
|
|
|
]; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
public function exportAction(SearchRaSecondFactorsCommand $command) |
102
|
|
|
{ |
103
|
|
|
$this->denyAccessUnlessGranted(['ROLE_RA']); |
104
|
|
|
|
105
|
|
|
$this->get('logger')->notice('Starting export of searched second factors'); |
106
|
|
|
|
107
|
|
|
$identity = $this->getCurrentUser(); |
108
|
|
|
$exportCommand = ExportRaSecondFactorsCommand::fromSearchCommand($command, $identity->institution); |
109
|
|
|
|
110
|
|
|
return $this->getSecondFactorService()->export($exportCommand); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* @param Request $request |
115
|
|
|
* @return \Symfony\Component\HttpFoundation\RedirectResponse |
116
|
|
|
*/ |
117
|
|
View Code Duplication |
public function revokeAction(Request $request) |
|
|
|
|
118
|
|
|
{ |
119
|
|
|
$this->denyAccessUnlessGranted(['ROLE_RA']); |
120
|
|
|
|
121
|
|
|
$logger = $this->get('logger'); |
122
|
|
|
|
123
|
|
|
$logger->notice('Received request to revoke Second Factor'); |
124
|
|
|
|
125
|
|
|
$command = new RevokeSecondFactorCommand(); |
126
|
|
|
$command->currentUserId = $this->getCurrentUser()->id; |
127
|
|
|
|
128
|
|
|
$form = $this->createForm(RevokeSecondFactorType::class, $command); |
129
|
|
|
$form->handleRequest($request); |
130
|
|
|
|
131
|
|
|
$logger->info(sprintf( |
132
|
|
|
'Sending middleware request to revoke Second Factor "%s" belonging to "%s" on behalf of "%s"', |
133
|
|
|
$command->secondFactorId, |
134
|
|
|
$command->identityId, |
135
|
|
|
$command->currentUserId |
136
|
|
|
)); |
137
|
|
|
|
138
|
|
|
$translator = $this->get('translator'); |
139
|
|
|
$flashBag = $this->get('session')->getFlashBag(); |
140
|
|
|
if ($this->getSecondFactorService()->revoke($command)) { |
141
|
|
|
$logger->notice('Second Factor revocation Succeeded'); |
142
|
|
|
$flashBag->add('success', $translator->trans('ra.second_factor.revocation.revoked')); |
143
|
|
|
} else { |
144
|
|
|
$logger->notice('Second Factor revocation Failed'); |
145
|
|
|
$flashBag->add('error', $translator->trans('ra.second_factor.revocation.could_not_revoke')); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
$logger->notice('Redirecting back to Second Factor Search Page'); |
149
|
|
|
|
150
|
|
|
return $this->redirectToRoute('ra_second_factors_search'); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* @param Request $request |
155
|
|
|
* @return Response |
156
|
|
|
*/ |
157
|
|
|
public function auditLogAction(Request $request) |
158
|
|
|
{ |
159
|
|
|
$this->denyAccessUnlessGranted(['ROLE_RA']); |
160
|
|
|
$logger = $this->get('logger'); |
161
|
|
|
|
162
|
|
|
$identityId = $request->get('identityId'); |
163
|
|
|
|
164
|
|
|
$logger->notice(sprintf('Requested AuditLog for SecondFactors of identity "%s"', $identityId)); |
165
|
|
|
|
166
|
|
|
$identity = $this->getIdentityService()->findById($identityId); |
167
|
|
|
if (!$identity) { |
168
|
|
|
$logger->notice(sprintf( |
169
|
|
|
'User with Identity "%s" requested non-existent identity "%s"', |
170
|
|
|
$this->getCurrentUser()->id, |
171
|
|
|
$identityId |
172
|
|
|
)); |
173
|
|
|
|
174
|
|
|
throw new NotFoundHttpException(); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
if ($identity->institution !== $this->getCurrentUser()->institution) { |
178
|
|
|
$logger->warning(sprintf( |
179
|
|
|
'User with Identity "%s" (%s) requested Identity "%s" (%s) of another institution, denying access', |
180
|
|
|
$this->getCurrentUser()->id, |
181
|
|
|
$this->getCurrentUser()->institution, |
182
|
|
|
$identity->id, |
183
|
|
|
$identity->institution |
184
|
|
|
)); |
185
|
|
|
|
186
|
|
|
throw $this->createAccessDeniedException(); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
$logger->info(sprintf('Retrieving audit log for Identity "%s"', $identity->id)); |
190
|
|
|
|
191
|
|
|
$command = new SearchSecondFactorAuditLogCommand(); |
192
|
|
|
$command->identityId = $identity->id; |
193
|
|
|
$command->institution = $identity->institution; |
194
|
|
|
$command->pageNumber = (int) $request->get('p', 1); |
195
|
|
|
$command->orderBy = $request->get('orderBy', 'recordedOn'); |
196
|
|
|
$command->orderDirection = $request->get('orderDirection', 'desc'); |
197
|
|
|
|
198
|
|
|
$auditLog = $this->getAuditLogService()->getAuditlog($command); |
199
|
|
|
|
200
|
|
|
$pagination = $this->get('knp_paginator')->paginate( |
201
|
|
|
$auditLog->getTotalItems() > 0 ? array_fill(0, $auditLog->getTotalItems(), 1) : [], |
202
|
|
|
$auditLog->getCurrentPage(), |
203
|
|
|
$auditLog->getItemsPerPage() |
204
|
|
|
); |
205
|
|
|
|
206
|
|
|
$logger->notice(sprintf('Audit log yielded "%d" results, rendering page', $auditLog->getTotalItems())); |
207
|
|
|
|
208
|
|
|
return $this->render( |
209
|
|
|
'SurfnetStepupRaRaBundle:SecondFactor:auditLog.html.twig', |
210
|
|
|
[ |
211
|
|
|
'pagination' => $pagination, |
212
|
|
|
'auditLog' => $auditLog, |
213
|
|
|
'identity' => $identity, |
214
|
|
|
] |
215
|
|
|
); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* @return \Surfnet\StepupRa\RaBundle\Service\RaSecondFactorService |
220
|
|
|
*/ |
221
|
|
|
private function getSecondFactorService() |
222
|
|
|
{ |
223
|
|
|
return $this->get('ra.service.ra_second_factor'); |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* @return \Surfnet\StepupRa\RaBundle\Service\IdentityService |
228
|
|
|
*/ |
229
|
|
|
private function getIdentityService() |
230
|
|
|
{ |
231
|
|
|
return $this->get('ra.service.identity'); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* @return \Surfnet\StepupRa\RaBundle\Service\AuditLogService |
236
|
|
|
*/ |
237
|
|
|
private function getAuditLogService() |
238
|
|
|
{ |
239
|
|
|
return $this->get('ra.service.audit_log'); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* @return \Surfnet\StepupMiddlewareClientBundle\Identity\Dto\Identity |
244
|
|
|
*/ |
245
|
|
|
private function getCurrentUser() |
246
|
|
|
{ |
247
|
|
|
return $this->get('security.token_storage')->getToken()->getUser(); |
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
/** |
251
|
|
|
* @return InstitutionConfigurationOptionsService |
252
|
|
|
*/ |
253
|
|
|
private function getInstitutionConfigurationOptionsService() |
254
|
|
|
{ |
255
|
|
|
return $this->get('ra.service.institution_configuration_options'); |
256
|
|
|
} |
257
|
|
|
} |
258
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.