Completed
Pull Request — develop (#284)
by
unknown
04:26 queued 02:09
created

applyCompliedWithVettedSecondFactorRevocationEvent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
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\StepupMiddleware\ApiBundle\Identity\Projector;
20
21
use Broadway\ReadModel\Projector;
22
use Surfnet\Stepup\Configuration\Event\InstitutionConfigurationRemovedEvent;
23
use Surfnet\Stepup\Configuration\Event\SelectRaaOptionChangedEvent;
24
use Surfnet\Stepup\Configuration\Event\SraaUpdatedEvent;
25
use Surfnet\Stepup\Identity\Collection\InstitutionCollection;
26
use Surfnet\Stepup\Identity\Event\CompliedWithVettedSecondFactorRevocationEvent;
27
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaaForInstitutionEvent;
28
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaForInstitutionEvent;
29
use Surfnet\Stepup\Identity\Event\RegistrationAuthorityRetractedForInstitutionEvent;
30
use Surfnet\Stepup\Identity\Event\VettedSecondFactorRevokedEvent;
31
use Surfnet\Stepup\Identity\Event\VettedSecondFactorsAllRevokedEvent;
32
use Surfnet\Stepup\Identity\Value\CommonName;
33
use Surfnet\Stepup\Identity\Value\Email;
34
use Surfnet\Stepup\Identity\Value\IdentityId;
35
use Surfnet\Stepup\Identity\Value\Institution;
36
use Surfnet\Stepup\Configuration\Value\Institution as ConfigurationInstitution;
37
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaaEvent;
38
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaEvent;
39
use Surfnet\Stepup\Identity\Event\IdentityForgottenEvent;
40
use Surfnet\Stepup\Identity\Event\RegistrationAuthorityRetractedEvent;
41
use Surfnet\Stepup\Identity\Event\SecondFactorVettedEvent;
42
use Surfnet\Stepup\Identity\Event\YubikeySecondFactorBootstrappedEvent;
43
use Surfnet\Stepup\Identity\Value\NameId;
44
use Surfnet\StepupMiddleware\ApiBundle\Configuration\Repository\InstitutionAuthorizationRepository;
45
use Surfnet\StepupMiddleware\ApiBundle\Identity\Entity\RaCandidate;
46
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\IdentityRepository;
47
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\RaCandidateRepository;
48
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\RaListingRepository;
49
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\RaSecondFactorRepository;
50
use Surfnet\StepupMiddleware\ApiBundle\Identity\Value\SecondFactorStatus;
51
52
/**
53
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
54
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
55
 */
56
class RaCandidateProjector extends Projector
57
{
58
    /**
59
     * @var RaCandidateRepository
60
     */
61
    private $raCandidateRepository;
62
63
    /**
64
     * @var RaListingRepository
65
     */
66
    private $raListingRepository;
67
68
    /**
69
     * @var institutionAuthorizationRepository
70
     */
71
    private $institutionAuthorizationRepository;
72
    /**
73
     * @var IdentityRepository
74
     */
75
    private $identityRepository;
76
    /**
77
     * @var RaSecondFactorRepository
78
     */
79
    private $raSecondFactorRepository;
80
81
    public function __construct(
82
        RaCandidateRepository $raCandidateRepository,
83
        RaListingRepository $raListingRepository,
84
        InstitutionAuthorizationRepository $institutionAuthorizationRepository,
85
        IdentityRepository $identityRepository,
86
        RaSecondFactorRepository $raSecondFactorRepository
87
    ) {
88
        $this->raCandidateRepository = $raCandidateRepository;
89
        $this->raListingRepository = $raListingRepository;
90
        $this->institutionAuthorizationRepository = $institutionAuthorizationRepository;
0 ignored issues
show
Documentation Bug introduced by
It seems like $institutionAuthorizationRepository of type object<Surfnet\StepupMid...uthorizationRepository> is incompatible with the declared type object<Surfnet\StepupMid...uthorizationRepository> of property $institutionAuthorizationRepository.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
91
        $this->identityRepository = $identityRepository;
92
        $this->raSecondFactorRepository = $raSecondFactorRepository;
93
    }
94
95
    /**
96
     * @param SecondFactorVettedEvent $event
97
     * @return void
98
     * @throws \Doctrine\ORM\NonUniqueResultException
99
     */
100
    public function applySecondFactorVettedEvent(SecondFactorVettedEvent $event)
101
    {
102
        $this->addCandidateToProjection(
103
            $event->identityInstitution,
104
            $event->identityId,
105
            $event->nameId,
106
            $event->commonName,
107
            $event->email
108
        );
109
    }
110
111
    /**
112
     * @param YubikeySecondFactorBootstrappedEvent $event
113
     * @return void
114
     * @throws \Doctrine\ORM\NonUniqueResultException
115
     */
116
    public function applyYubikeySecondFactorBootstrappedEvent(YubikeySecondFactorBootstrappedEvent $event)
117
    {
118
        $this->addCandidateToProjection(
119
            $event->identityInstitution,
120
            $event->identityId,
121
            $event->nameId,
122
            $event->commonName,
123
            $event->email
124
        );
125
    }
126
127
    /**
128
     * If all vetted tokens are removed we should prevent the identity from becoming an RA candidate
129
     *
130
     * @param VettedSecondFactorsAllRevokedEvent $event
131
     */
132
    public function applyVettedSecondFactorsAllRevokedEvent(
133
        VettedSecondFactorsAllRevokedEvent $event
134
    ) {
135
        $this->raCandidateRepository->removeByIdentityId($event->identityId);
136
    }
137
138
    /**
139
     * @param SraaUpdatedEvent $event
140
     *
141
     * Removes all RaCandidates that have a nameId matching an SRAA, as they cannot be made RA(A) as they
142
     * already are SRAA.
143
     */
144
    public function applySraaUpdatedEvent(SraaUpdatedEvent $event)
145
    {
146
        $this->raCandidateRepository->removeByNameIds($event->sraaList);
147
    }
148
149
    /**
150
     * @param IdentityAccreditedAsRaForInstitutionEvent $event
151
     * @return void
152
     */
153
    public function applyIdentityAccreditedAsRaForInstitutionEvent(IdentityAccreditedAsRaForInstitutionEvent $event)
154
    {
155
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->raInstitution);
156
    }
157
158
    /**
159
     * @param IdentityAccreditedAsRaaForInstitutionEvent $event
160
     * @return void
161
     */
162
    public function applyIdentityAccreditedAsRaaForInstitutionEvent(IdentityAccreditedAsRaaForInstitutionEvent $event)
163
    {
164
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->raInstitution);
165
    }
166
167
    /**
168
     * @param RegistrationAuthorityRetractedForInstitutionEvent $event
169
     * @return void
170
     */
171 View Code Duplication
    public function applyRegistrationAuthorityRetractedForInstitutionEvent(RegistrationAuthorityRetractedForInstitutionEvent $event)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
172
    {
173
        $candidate = RaCandidate::nominate(
174
            $event->identityId,
175
            $event->identityInstitution,
176
            $event->nameId,
177
            $event->commonName,
178
            $event->email,
179
            $event->raInstitution
180
        );
181
182
        $this->raCandidateRepository->merge($candidate);
183
    }
184
185
    protected function applyIdentityForgottenEvent(IdentityForgottenEvent $event)
186
    {
187
        $this->raCandidateRepository->removeByIdentityId($event->identityId);
188
    }
189
190
    protected function applySelectRaaOptionChangedEvent(SelectRaaOptionChangedEvent $event)
191
    {
192
        $authorizedInstitutions = $event->selectRaaOption->getInstitutions($event->institution);
193
        $this->updateInstitutionCandidatesFromCollection(new Institution($event->institution->getInstitution()), $authorizedInstitutions);
194
    }
195
196
    protected function applyInstitutionConfigurationRemovedEvent(InstitutionConfigurationRemovedEvent $event)
197
    {
198
        $this->raCandidateRepository->removeByRaInstitution(new Institution($event->institution->getInstitution()));
199
    }
200
201
    /**
202
     * This method is kept to be backwards compatible for changes before FGA
203
     *
204
     * @param IdentityAccreditedAsRaEvent $event
205
     * @return void
206
     */
207
    public function applyIdentityAccreditedAsRaEvent(IdentityAccreditedAsRaEvent $event)
208
    {
209
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->identityInstitution);
210
    }
211
212
    /**
213
     * This method is kept to be backwards compatible for changes before FGA
214
     *
215
     * @param IdentityAccreditedAsRaaEvent $event
216
     * @return void
217
     */
218
    public function applyIdentityAccreditedAsRaaEvent(IdentityAccreditedAsRaaEvent $event)
219
    {
220
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->identityInstitution);
221
    }
222
223
    /**
224
     * This method is kept to be backwards compatible for changes before FGA
225
     *
226
     * @param RegistrationAuthorityRetractedEvent $event
227
     * @return void
228
     */
229 View Code Duplication
    public function applyRegistrationAuthorityRetractedEvent(RegistrationAuthorityRetractedEvent $event)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
230
    {
231
        $candidate = RaCandidate::nominate(
232
            $event->identityId,
233
            $event->identityInstitution,
234
            $event->nameId,
235
            $event->commonName,
236
            $event->email,
237
            $event->identityInstitution
238
        );
239
240
        $this->raCandidateRepository->merge($candidate);
241
    }
242
243
    /**
244
     * @param Institution $institution
245
     * @param ConfigurationInstitution[] $authorizedInstitutions
246
     * @throws \Doctrine\ORM\NonUniqueResultException
247
     */
248
    private function updateInstitutionCandidatesFromCollection(Institution $institution, array $authorizedInstitutions)
249
    {
250
        // convert configuration to value institutions
251
        $raInstitutions = new InstitutionCollection();
252
        foreach ($authorizedInstitutions as $authorizedInstitution) {
253
            $raInstitutions->add(new Institution($authorizedInstitution->getInstitution()));
254
        }
255
256
        // Remove candidates from removed institutions
257
        $this->raCandidateRepository->removeInstitutionsNotInList($institution, $raInstitutions);
258
259
        // loop through authorized institutions
260
        foreach ($raInstitutions as $raInstitution) {
261
            // add new identities
262
            $raSecondFactors = $this->raSecondFactorRepository->findByInstitution($raInstitution->getInstitution());
263
264
            foreach ($raSecondFactors as $raSecondFactor) {
265
                if (!$raSecondFactor->status->equals(SecondFactorStatus::vetted())) {
266
                    continue;
267
                }
268
269
                $identity = $this->identityRepository->find($raSecondFactor->identityId);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $identity is correct as $this->identityRepositor...condFactor->identityId) (which targets Surfnet\StepupMiddleware...ntityRepository::find()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
270
                if ($identity) {
271
                    $identityId = new IdentityId($identity->id);
272
273
                    // check if persistent in ra listing
274
                    if ($this->raListingRepository->findByIdentityIdAndRaInstitution($identityId, $institution)) {
275
                        continue;
276
                    }
277
278
                    // create candidate if not exists
279
                    $candidate = $this->raCandidateRepository->findByIdentityIdAndRaInstitution($identityId, $institution);
280
                    if (!$candidate) {
281
                        $candidate = RaCandidate::nominate(
282
                            $identityId,
283
                            $identity->institution,
284
                            $identity->nameId,
285
                            $identity->commonName,
286
                            $identity->email,
287
                            $institution
288
                        );
289
                    }
290
291
                    // store
292
                    $this->raCandidateRepository->merge($candidate);
293
                }
294
            }
295
        }
296
    }
297
298
    /**
299
     * @param Institution $identityInstitution
300
     * @param IdentityId $identityId
301
     * @param NameId $identityNameId
302
     * @param CommonName $identityCommonName
303
     * @param Email $identityEmail
304
     * @throws \Doctrine\ORM\NonUniqueResultException
305
     */
306
    private function addCandidateToProjection(
307
        Institution $identityInstitution,
308
        IdentityId $identityId,
309
        NameId $identityNameId,
310
        CommonName $identityCommonName,
311
        Email $identityEmail
312
    ) {
313
        $institutionAuthorizations = $this->institutionAuthorizationRepository
314
            ->findAuthorizationOptionsForInstitution(new ConfigurationInstitution($identityInstitution->getInstitution()));
315
316
        $institutions = [];
317
        foreach ($institutionAuthorizations as $authorization) {
318
            $raInstitutionName = $authorization->institutionRelation->getInstitution();
319
            $institutions[$raInstitutionName] = new Institution($raInstitutionName);
320
        }
321
322
        foreach ($institutions as $institution) {
323
            if ($this->raListingRepository->findByIdentityIdAndInstitution($identityId, $institution)) {
324
                continue;
325
            }
326
327
            // create candidate if not exists
328
            $candidate = $this->raCandidateRepository->findByIdentityIdAndRaInstitution($identityId, $institution);
329
            if (!$candidate) {
330
                $candidate = RaCandidate::nominate(
331
                    $identityId,
332
                    $identityInstitution,
333
                    $identityNameId,
334
                    $identityCommonName,
335
                    $identityEmail,
336
                    $institution
337
                );
338
            }
339
340
            $this->raCandidateRepository->merge($candidate);
341
        }
342
    }
343
}
344