Completed
Push — feature/fine-grained-authoriza... ( 7000b8...be2531 )
by
unknown
26:33 queued 44s
created

SelfServiceBundle/Service/IdentityService.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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\StepupSelfService\SelfServiceBundle\Service;
20
21
use Exception;
22
use Psr\Log\LoggerInterface;
23
use Surfnet\StepupBundle\Command\SwitchLocaleCommand;
24
use Surfnet\StepupMiddlewareClient\Identity\Dto\IdentitySearchQuery;
25
use Surfnet\StepupMiddlewareClientBundle\Identity\Command\CreateIdentityCommand;
26
use Surfnet\StepupMiddlewareClientBundle\Identity\Command\ExpressLocalePreferenceCommand;
27
use Surfnet\StepupMiddlewareClientBundle\Identity\Command\UpdateIdentityCommand;
28
use Surfnet\StepupMiddlewareClientBundle\Identity\Dto\Identity;
29
use Surfnet\StepupMiddlewareClientBundle\Identity\Service\IdentityService as ApiIdentityService;
30
use Surfnet\StepupSelfService\SelfServiceBundle\Exception\RuntimeException;
31
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
32
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
33
use Symfony\Component\Security\Core\User\UserInterface;
34
use Symfony\Component\Security\Core\User\UserProviderInterface;
35
36
/**
37
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects) -- Hard to reduce due to different commands and queries used.
38
 */
39
class IdentityService implements UserProviderInterface
40
{
41
    /**
42
     * @var \Surfnet\StepupMiddlewareClientBundle\Identity\Service\IdentityService
43
     */
44
    private $apiIdentityService;
45
46
    /**
47
     * @var \Surfnet\StepupMiddlewareClientBundle\Service\CommandService
48
     */
49
    private $commandService;
50
51
    /**
52
     * @var \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface
53
     */
54
    private $tokenStorage;
55
56
    /**
57
     * @var \Psr\Log\LoggerInterface
58
     */
59
    private $logger;
60
61
    public function __construct(
62
        ApiIdentityService $apiIdentityService,
63
        CommandService $commandService,
64
        TokenStorageInterface $tokenStorage,
65
        LoggerInterface $logger
66
    ) {
67
        $this->apiIdentityService = $apiIdentityService;
68
        $this->commandService = $commandService;
69
        $this->tokenStorage = $tokenStorage;
70
        $this->logger = $logger;
71
    }
72
73
    /**
74
     * For now this functionality is disabled, unsure if actually needed
75
     *
76
     * If needed, the username is the UUID of the identity so it can be fetched rather easy
77
     */
78
    public function loadUserByUsername($username)
79
    {
80
        throw new RuntimeException(sprintf('Cannot Load User By Username "%s"', $username));
81
    }
82
83
    /**
84
     * For now this functionality is disabled, unsure if actually needed
85
     */
86
    public function refreshUser(UserInterface $user)
87
    {
88
        throw new RuntimeException(sprintf('Cannot Refresh User "%s"', $user->getUsername()));
89
    }
90
91
    /**
92
     * Whether this provider supports the given user class
93
     *
94
     * @param string $class
95
     *
96
     * @return bool
97
     */
98
    public function supportsClass($class)
99
    {
100
        return $class === 'Surfnet\StepupMiddlewareClientBundle\Identity\Dto\Identity';
101
    }
102
103
    /**
104
     * @param string $nameId
105
     * @param string $institution
106
     * @return null|\Surfnet\StepupMiddlewareClientBundle\Identity\Dto\Identity
107
     * @throws \Surfnet\StepupSelfService\SelfServiceBundle\Exception\RuntimeException
108
     */
109
    public function findByNameIdAndInstitution($nameId, $institution)
110
    {
111
        $searchQuery = new IdentitySearchQuery($institution);
112
        $searchQuery->setNameId($nameId);
113
114
        try {
115
            $result = $this->apiIdentityService->search($searchQuery);
116
        } catch (Exception $e) {
117
            $message = sprintf('Exception when searching identity: "%s"', $e->getMessage());
118
            $this->logger->critical($message);
119
            throw new RuntimeException($message, 0, $e);
120
        }
121
122
        $elements = $result->getElements();
123
        if (count($elements) === 0) {
124
            return null;
125
        }
126
127
        if (count($elements) === 1) {
128
            return reset($elements);
129
        }
130
131
        throw new RuntimeException(sprintf(
132
            'Got an unexpected amount of identities, expected 0 or 1, got "%d"',
133
            count($elements)
134
        ));
135
    }
136
137
    /**
138
     * Save or Update an existing Identity
139
     *
140
     * @param Identity $identity
141
     */
142
    public function createIdentity(Identity $identity)
143
    {
144
        $command = new CreateIdentityCommand();
145
        $command->id              = $identity->id;
146
        $command->nameId          = $identity->nameId;
147
        $command->institution     = $identity->institution;
148
        $command->email           = $identity->email;
149
        $command->commonName      = $identity->commonName;
150
        $command->preferredLocale = $identity->preferredLocale;
151
152
        $this->processCommand($command);
153
    }
154
155
    /**
156
     * @param Identity $identity
157
     */
158
    public function updateIdentity(Identity $identity)
159
    {
160
        $command = new UpdateIdentityCommand($identity->id, $identity->institution);
161
        $command->email      = $identity->email;
162
        $command->commonName = $identity->commonName;
163
164
        $this->processCommand($command);
165
    }
166
167
168
    /**
169
     * @param SwitchLocaleCommand $command
170
     * @return bool
171
     */
172
    public function switchLocale(SwitchLocaleCommand $command)
173
    {
174
        /** @var TokenInterface|null */
175
        $token = $this->tokenStorage->getToken();
176
177
        if (!$token) {
178
            throw new RuntimeException('Cannot switch locales when unauthenticated');
179
        }
180
181
        /** @var Identity $identity */
182
        $identity = $token->getUser();
183
184
        $expressLocalePreferenceCommand = new ExpressLocalePreferenceCommand();
185
        $expressLocalePreferenceCommand->identityId = $command->identityId;
186
        $expressLocalePreferenceCommand->preferredLocale = $command->locale;
187
188
        $result = $this->commandService->execute($expressLocalePreferenceCommand);
0 ignored issues
show
The call to execute() misses a required argument $metadata.

This check looks for function calls that miss required arguments.

Loading history...
189
190
        if ($result->isSuccessful()) {
191
            $identity->preferredLocale = $command->locale;
192
        }
193
194
        return $result->isSuccessful();
195
    }
196
197
    /**
198
     * @param $command
199
     */
200
    public function processCommand($command)
201
    {
202
        $messageTemplate = 'Exception when saving Identity[%s]: with command "%s", error: "%s"';
203
204
        try {
205
            $result = $this->commandService->execute($command);
0 ignored issues
show
The call to execute() misses a required argument $metadata.

This check looks for function calls that miss required arguments.

Loading history...
206
        } catch (Exception $e) {
207
            $message = sprintf($messageTemplate, $command->id, get_class($command), $e->getMessage());
208
            $this->logger->critical($message);
209
210
            throw new RuntimeException($message, 0, $e);
211
        }
212
213
        if (!$result->isSuccessful()) {
214
            $note = sprintf($messageTemplate, $command->id, get_class($command), implode('", "', $result->getErrors()));
215
            $this->logger->critical($note);
216
217
            throw new RuntimeException($note);
218
        }
219
    }
220
}
221