Completed
Push — feature/create-rv-customizable... ( 5ff1d9...05c7d4 )
by
unknown
01:53
created

RemoteVettingController::remoteVetAction()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.552
c 0
b 0
f 0
cc 4
nc 2
nop 3
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\SamlCalloutHelper;
34
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\Value\FeedbackCollection;
35
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVetting\Value\ProcessId;
36
use Surfnet\StepupSelfService\SelfServiceBundle\Service\RemoteVettingService;
37
use Surfnet\StepupSelfService\SelfServiceBundle\Service\SecondFactorService;
38
use Symfony\Component\HttpFoundation\RedirectResponse;
39
use Symfony\Component\HttpFoundation\Request;
40
use Symfony\Component\HttpFoundation\Response;
41
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
42
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
43
44
/**
45
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) Too much coupling dus to glue code nature of this controller.
46
 *                                                 Could be refactored later on
47
 */
48
class RemoteVettingController extends Controller
49
{
50
    /**
51
     * @var RemoteVettingService
52
     */
53
    private $remoteVettingService;
54
    /**
55
     * @var SamlCalloutHelper
56
     */
57
    private $samlCalloutHelper;
58
    /**
59
     * @var LoggerInterface
60
     */
61
    private $logger;
62
    /**
63
     * @var RegistrationExpirationHelper
64
     */
65
    private $expirationHelper;
66
    /**
67
     * @var SecondFactorService
68
     */
69
    private $secondFactorService;
70
71
    public function __construct(
72
        RemoteVettingService $remoteVettingService,
73
        SecondFactorService $secondFactorService,
74
        SamlCalloutHelper $samlCalloutHelper,
75
        RegistrationExpirationHelper $expirationHelper,
76
        LoggerInterface $logger
77
    ) {
78
        $this->secondFactorService = $secondFactorService;
79
        $this->remoteVettingService = $remoteVettingService;
80
        $this->samlCalloutHelper = $samlCalloutHelper;
81
        $this->expirationHelper = $expirationHelper;
82
        $this->logger = $logger;
83
    }
84
85
    /**
86
     * @Template
87
     * @param Request $request
88
     * @param string $secondFactorId
89
     * @param string $identityProviderSlug
90
     * @return array|Response
91
     */
92
    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...
93
    {
94
        $identity = $this->getIdentity();
95
96
        $secondFactor = $this->secondFactorService->findOneVerified($secondFactorId);
97
        if ($secondFactor === null ||
98
            $secondFactor->identityId != $identity->id ||
99
            $this->expirationHelper->hasExpired($secondFactor->registrationRequestedAt)
100
        ) {
101
            throw new NotFoundHttpException(
102
                sprintf("No %s second factor with id '%s' exists.", 'verified', $secondFactorId)
103
            );
104
        }
105
106
        $token = RemoteVettingTokenDto::create(
107
            $identity->id,
108
            $secondFactor->id
109
        );
110
111
        $this->remoteVettingService->start($identityProviderSlug, $token);
112
113
        return new RedirectResponse($this->samlCalloutHelper->createAuthnRequest($identityProviderSlug));
114
    }
115
116
    /**
117
     * @param Request $request
118
     * @return mixed
119
     */
120
    public function acsAction(Request $request)
121
    {
122
        $this->logger->info('Receiving response from the remote IdP');
123
124
        /** @var FlashBagInterface $flashBag */
125
        $flashBag = $this->get('session')->getFlashBag();
126
127
        $this->logger->info('Load the attributes from the saml response');
128
129
        try {
130
            $processId = $this->samlCalloutHelper->handleResponse($request, $this->remoteVettingService->getActiveIdentityProviderSlug());
131
        } catch (InvalidRemoteVettingStateException $e) {
132
            $this->logger->error($e->getMessage());
133
            $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
134
            return $this->redirectToRoute('ss_second_factor_list');
135
        } catch (PreconditionNotMetException $e) {
136
            $this->logger->error($e->getMessage());
137
            $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
138
            return $this->redirectToRoute('ss_second_factor_list');
139
        } catch (InvalidRemoteVettingContextException $e) {
140
            $this->logger->error($e->getMessage());
141
            return $this->redirectToRoute('ss_second_factor_list');
142
        }
143
144
        return $this->redirectToRoute('ss_second_factor_remote_vet_match', [
145
            'processId' => $processId->getProcessId(),
146
        ]);
147
148
        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...
149
    }
150
151
    /**
152
     * @param Request $request
153
     * @param $processId
154
     * @return Response
155
     */
156
    public function remoteVetMatchAction(Request $request, $processId)
157
    {
158
        /** @var FlashBagInterface $flashBag */
159
        $flashBag = $this->get('session')->getFlashBag();
160
161
        /** @var SamlToken $samlToken */
162
        $samlToken = $this->container->get('security.token_storage')->getToken();
163
164
        $localAttributes = AttributeListDto::fromAttributeSet($samlToken->getAttribute(SamlToken::ATTRIBUTE_SET));
165
166
        $matches = $this->remoteVettingService->getAttributeMatchCollection($localAttributes);
167
        $command = new RemoteVetValidationCommand($matches, new FeedbackCollection());
168
169
        try {
170
            $form = $this->createForm(RemoteVetValidationType::class, $command)->handleRequest($request);
171
            if ($form->isSubmitted() && $form->isValid()) {
172
173
                /** @var RemoteVetValidationCommand $command */
174
                $command = $form->getData();
175
176
                $token =  $this->remoteVettingService->done(
177
                    ProcessId::create($processId),
178
                    $this->getIdentity(),
179
                    $localAttributes,
180
                    $command->matches,
181
                    $command->feedback
182
                );
183
184
                $command = new RemoteVetCommand();
185
                $command->identity = $token->getIdentityId();
186
                $command->secondFactor = $token->getSecondFactorId();
187
188
                if ($this->secondFactorService->remoteVet($command)) {
189
                    $flashBag->add('success', 'ss.second_factor.revoke.alert.remote_vetting_successful');
190
                } else {
191
                    $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
192
                }
193
194
                return $this->redirectToRoute('ss_second_factor_list');
195
            }
196
197
            return $this->render('SurfnetStepupSelfServiceSelfServiceBundle:remote_vetting:validation.html.twig', [
198
                'form' => $form->createView(),
199
            ]);
200
        } catch (InvalidRemoteVettingStateException $e) {
201
            $this->logger->error($e->getMessage());
202
            $flashBag->add('error', 'ss.second_factor.revoke.alert.remote_vetting_failed');
203
            return $this->redirectToRoute('ss_second_factor_list');
204
        } catch (InvalidRemoteVettingContextException $e) {
205
            $this->logger->error($e->getMessage());
206
            return $this->redirectToRoute('ss_second_factor_list');
207
        }
208
    }
209
}
210