Completed
Pull Request — develop (#225)
by
unknown
09:12 queued 07:20
created

RemoteVettingController::remoteVetMatchAction()   B

Complexity

Conditions 6
Paths 41

Size

Total Lines 63

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 63
rs 8.185
c 0
b 0
f 0
cc 6
nc 41
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Copyright 2010 SURFnet B.V.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *     http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
namespace Surfnet\StepupSelfService\SelfServiceBundle\Controller;
19
20
use Psr\Log\LoggerInterface;
21
use SAML2\Response\Exception\PreconditionNotMetException;
22
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
23
use Surfnet\StepupBundle\DateTime\RegistrationExpirationHelper;
24
use Surfnet\StepupSelfService\SelfServiceBundle\Command\RemoteVetCommand;
25
use Surfnet\StepupSelfService\SelfServiceBundle\Command\RemoteVetValidationCommand;
26
use Surfnet\StepupSelfService\SelfServiceBundle\Exception\InvalidRemoteVettingContextException;
27
use Surfnet\StepupSelfService\SelfServiceBundle\Exception\InvalidRemoteVettingStateException;
28
use Surfnet\StepupSelfService\SelfServiceBundle\Form\Type\RemoteVetSecondFactorType;
29
use Surfnet\StepupSelfService\SelfServiceBundle\Form\Type\RemoteVetValidationType;
30
use Surfnet\StepupSelfService\SelfServiceBundle\Security\Authentication\Token\SamlToken;
31
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\Dto\AttributeListDto;
32
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\Dto\RemoteVettingTokenDto;
33
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\RemoteVettingViewHelper;
34
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\SamlCalloutHelper;
35
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\Value\FeedbackCollection;
36
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\Value\ProcessId;
37
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVettingService;
38
use Surfnet\StepupSelfService\SelfServiceBundle\Service\SecondFactorService;
39
use Symfony\Component\HttpFoundation\RedirectResponse;
40
use Symfony\Component\HttpFoundation\Request;
41
use Symfony\Component\HttpFoundation\Response;
42
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
43
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
44
45
/**
46
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) Too much coupling dus to glue code nature of this controller.
47
 *                                                 Could be refactored later on
48
 */
49
class RemoteVettingController extends Controller
50
{
51
    /**
52
     * @var RemoteVettingService
53
     */
54
    private $remoteVettingService;
55
    /**
56
     * @var SamlCalloutHelper
57
     */
58
    private $samlCalloutHelper;
59
    /**
60
     * @var LoggerInterface
61
     */
62
    private $logger;
63
    /**
64
     * @var RegistrationExpirationHelper
65
     */
66
    private $expirationHelper;
67
    /**
68
     * @var SecondFactorService
69
     */
70
    private $secondFactorService;
71
    /**
72
     * @var RemoteVettingViewHelper
73
     */
74
    private $remoteVettingViewHelper;
75
76
    public function __construct(
77
        RemoteVettingService $remoteVettingService,
78
        RemoteVettingViewHelper $remoteVettingViewHelper,
79
        SecondFactorService $secondFactorService,
80
        SamlCalloutHelper $samlCalloutHelper,
81
        RegistrationExpirationHelper $expirationHelper,
82
        LoggerInterface $logger
83
    ) {
84
        $this->secondFactorService = $secondFactorService;
85
        $this->remoteVettingService = $remoteVettingService;
86
        $this->samlCalloutHelper = $samlCalloutHelper;
87
        $this->expirationHelper = $expirationHelper;
88
        $this->logger = $logger;
89
        $this->remoteVettingViewHelper = $remoteVettingViewHelper;
90
    }
91
92
    /**
93
     * @Template
94
     * @param Request $request
95
     * @param string $secondFactorId
96
     * @param string $identityProviderSlug
97
     * @return array|Response
98
     */
99
    public function remoteVetAction(Request $request, $secondFactorId, $identityProviderSlug)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
100
    {
101
        $identity = $this->getIdentity();
102
103
        $secondFactor = $this->secondFactorService->findOneVerified($secondFactorId);
104
        if ($secondFactor === null ||
105
            $secondFactor->identityId != $identity->id ||
106
            $this->expirationHelper->hasExpired($secondFactor->registrationRequestedAt)
107
        ) {
108
            throw new NotFoundHttpException(
109
                sprintf("No %s second factor with id '%s' exists.", 'verified', $secondFactorId)
110
            );
111
        }
112
113
        $token = RemoteVettingTokenDto::create(
114
            $identity->id,
115
            $secondFactor->id
116
        );
117
118
        $this->remoteVettingService->start($identityProviderSlug, $token);
119
120
        return new RedirectResponse($this->samlCalloutHelper->createAuthnRequest($identityProviderSlug));
121
    }
122
123
    /**
124
     * @param Request $request
125
     * @return mixed
126
     */
127
    public function acsAction(Request $request)
128
    {
129
        $this->logger->info('Receiving a remote vetting response from the remote IdP');
130
131
        /** @var FlashBagInterface $flashBag */
132
        $flashBag = $this->get('session')->getFlashBag();
133
134
        try {
135
            $processId = $this->samlCalloutHelper->handleResponse($request, $this->remoteVettingService->getActiveIdentityProviderSlug());
136
        } catch (InvalidRemoteVettingStateException $e) {
137
            $this->logger->error($e->getMessage());
138
            $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
139
            return $this->redirectToRoute('ss_second_factor_list');
140
        } catch (PreconditionNotMetException $e) {
141
            $this->logger->error($e->getMessage());
142
            $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
143
            return $this->redirectToRoute('ss_second_factor_list');
144
        } catch (InvalidRemoteVettingContextException $e) {
145
            $this->logger->error($e->getMessage());
146
            $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_invalid_context');
147
            return $this->redirectToRoute('ss_second_factor_list');
148
        }
149
150
        return $this->redirectToRoute('ss_second_factor_remote_vet_match', [
151
            'processId' => $processId->getProcessId(),
152
        ]);
153
154
        return $this->redirectToRoute('ss_second_factor_list');
0 ignored issues
show
Unused Code introduced by
return $this->redirectTo...s_second_factor_list'); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
155
    }
156
157
    /**
158
     * @param Request $request
159
     * @param $processId
160
     * @return Response
161
     */
162
    public function remoteVetMatchAction(Request $request, $processId)
163
    {
164
        $this->logger->info('Start matching the remote vetting attributes');
165
166
        /** @var FlashBagInterface $flashBag */
167
        $flashBag = $this->get('session')->getFlashBag();
168
169
        /** @var SamlToken $samlToken */
170
        $samlToken = $this->container->get('security.token_storage')->getToken();
171
172
        $localAttributes = AttributeListDto::fromAttributeSet($samlToken->getAttribute(SamlToken::ATTRIBUTE_SET));
173
174
        try {
175
            $matches = $this->remoteVettingService->getAttributeMatchCollection($localAttributes);
176
            $command = new RemoteVetValidationCommand($matches, new FeedbackCollection());
177
178
            $form = $this->createForm(RemoteVetValidationType::class, $command)->handleRequest($request);
179
            if ($form->isSubmitted() && $form->isValid()) {
180
                $this->logger->info('Finishing matching the remote vetting attributes');
181
182
                /** @var RemoteVetValidationCommand $command */
183
                $command = $form->getData();
184
185
                $token =  $this->remoteVettingService->done(
186
                    ProcessId::create($processId),
187
                    $this->getIdentity(),
188
                    $localAttributes,
189
                    $command->matches,
190
                    $command->feedback
191
                );
192
193
                $command = new RemoteVetCommand();
194
                $command->identity = $token->getIdentityId();
195
                $command->secondFactor = $token->getSecondFactorId();
196
197
                if ($this->secondFactorService->remoteVet($command)) {
198
                    $this->logger->info('Remote vetting succeeded');
199
                    $flashBag->add('success', 'ss.second_factor.revoke.alert.remote_vetting_successful');
200
                } else {
201
                    $this->logger->info('Remote vetting failed');
202
                    $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
203
                }
204
205
                return $this->redirectToRoute('ss_second_factor_list');
206
            }
207
            
208
            $provider = $this->remoteVettingViewHelper->getIdentityProvider($this->remoteVettingService->getActiveIdentityProviderSlug());
209
210
            return $this->render('SurfnetStepupSelfServiceSelfServiceBundle:remote_vetting:validation.html.twig', [
211
                'provider' => $provider,
212
                'identity' => $this->getIdentity(),
213
                'form' => $form->createView(),
214
            ]);
215
        } catch (InvalidRemoteVettingStateException $e) {
216
            $this->logger->error($e->getMessage());
217
            $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
218
            return $this->redirectToRoute('ss_second_factor_list');
219
        } catch (InvalidRemoteVettingContextException $e) {
220
            $this->logger->error($e->getMessage());
221
            $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_invalid_context');
222
            return $this->redirectToRoute('ss_second_factor_list');
223
        }
224
    }
225
}
226