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

applyVettedSecondFactorsAllRevokedEvent()   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\IdentityAccreditedAsRaaForInstitutionEvent;
27
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaForInstitutionEvent;
28
use Surfnet\Stepup\Identity\Event\RegistrationAuthorityRetractedForInstitutionEvent;
29
use Surfnet\Stepup\Identity\Event\VettedSecondFactorsAllRevokedEvent;
30
use Surfnet\Stepup\Identity\Value\CommonName;
31
use Surfnet\Stepup\Identity\Value\Email;
32
use Surfnet\Stepup\Identity\Value\IdentityId;
33
use Surfnet\Stepup\Identity\Value\Institution;
34
use Surfnet\Stepup\Configuration\Value\Institution as ConfigurationInstitution;
35
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaaEvent;
36
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaEvent;
37
use Surfnet\Stepup\Identity\Event\IdentityForgottenEvent;
38
use Surfnet\Stepup\Identity\Event\RegistrationAuthorityRetractedEvent;
39
use Surfnet\Stepup\Identity\Event\SecondFactorVettedEvent;
40
use Surfnet\Stepup\Identity\Event\YubikeySecondFactorBootstrappedEvent;
41
use Surfnet\Stepup\Identity\Value\NameId;
42
use Surfnet\StepupMiddleware\ApiBundle\Configuration\Repository\InstitutionAuthorizationRepository;
43
use Surfnet\StepupMiddleware\ApiBundle\Identity\Entity\RaCandidate;
44
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\IdentityRepository;
45
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\RaCandidateRepository;
46
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\RaListingRepository;
47
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\RaSecondFactorRepository;
48
49
/**
50
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
51
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
52
 */
53
class RaCandidateProjector extends Projector
54
{
55
    /**
56
     * @var RaCandidateRepository
57
     */
58
    private $raCandidateRepository;
59
60
    /**
61
     * @var RaListingRepository
62
     */
63
    private $raListingRepository;
64
65
    /**
66
     * @var institutionAuthorizationRepository
67
     */
68
    private $institutionAuthorizationRepository;
69
    /**
70
     * @var IdentityRepository
71
     */
72
    private $identityRepository;
73
    /**
74
     * @var RaSecondFactorRepository
75
     */
76
    private $raSecondFactorRepository;
77
78
    public function __construct(
79
        RaCandidateRepository $raCandidateRepository,
80
        RaListingRepository $raListingRepository,
81
        InstitutionAuthorizationRepository $institutionAuthorizationRepository,
82
        IdentityRepository $identityRepository,
83
        RaSecondFactorRepository $raSecondFactorRepository
84
    ) {
85
        $this->raCandidateRepository = $raCandidateRepository;
86
        $this->raListingRepository = $raListingRepository;
87
        $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...
88
        $this->identityRepository = $identityRepository;
89
        $this->raSecondFactorRepository = $raSecondFactorRepository;
90
    }
91
92
    /**
93
     * @param SecondFactorVettedEvent $event
94
     * @return void
95
     * @throws \Doctrine\ORM\NonUniqueResultException
96
     */
97
    public function applySecondFactorVettedEvent(SecondFactorVettedEvent $event)
98
    {
99
        $this->addCandidateToProjection(
100
            $event->identityInstitution,
101
            $event->identityId,
102
            $event->nameId,
103
            $event->commonName,
104
            $event->email
105
        );
106
    }
107
108
    /**
109
     * @param YubikeySecondFactorBootstrappedEvent $event
110
     * @return void
111
     * @throws \Doctrine\ORM\NonUniqueResultException
112
     */
113
    public function applyYubikeySecondFactorBootstrappedEvent(YubikeySecondFactorBootstrappedEvent $event)
114
    {
115
        $this->addCandidateToProjection(
116
            $event->identityInstitution,
117
            $event->identityId,
118
            $event->nameId,
119
            $event->commonName,
120
            $event->email
121
        );
122
    }
123
124
    /**
125
     * If all vetted tokens are removed we should prevent the identity from becoming an RA candidate
126
     *
127
     * @param VettedSecondFactorsAllRevokedEvent $event
128
     */
129
    public function applyVettedSecondFactorsAllRevokedEvent(
130
        VettedSecondFactorsAllRevokedEvent $event
131
    ) {
132
        $this->raCandidateRepository->removeByIdentityId($event->identityId);
133
    }
134
135
    /**
136
     * @param SraaUpdatedEvent $event
137
     *
138
     * Removes all RaCandidates that have a nameId matching an SRAA, as they cannot be made RA(A) as they
139
     * already are SRAA.
140
     */
141
    public function applySraaUpdatedEvent(SraaUpdatedEvent $event)
142
    {
143
        $this->raCandidateRepository->removeByNameIds($event->sraaList);
144
    }
145
146
    /**
147
     * @param IdentityAccreditedAsRaForInstitutionEvent $event
148
     * @return void
149
     */
150
    public function applyIdentityAccreditedAsRaForInstitutionEvent(IdentityAccreditedAsRaForInstitutionEvent $event)
151
    {
152
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->raInstitution);
153
    }
154
155
    /**
156
     * @param IdentityAccreditedAsRaaForInstitutionEvent $event
157
     * @return void
158
     */
159
    public function applyIdentityAccreditedAsRaaForInstitutionEvent(IdentityAccreditedAsRaaForInstitutionEvent $event)
160
    {
161
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->raInstitution);
162
    }
163
164
    /**
165
     * @param RegistrationAuthorityRetractedForInstitutionEvent $event
166
     * @return void
167
     */
168 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...
169
    {
170
        $candidate = RaCandidate::nominate(
171
            $event->identityId,
172
            $event->identityInstitution,
173
            $event->nameId,
174
            $event->commonName,
175
            $event->email,
176
            $event->raInstitution
177
        );
178
179
        $this->raCandidateRepository->merge($candidate);
180
    }
181
182
    protected function applyIdentityForgottenEvent(IdentityForgottenEvent $event)
183
    {
184
        $this->raCandidateRepository->removeByIdentityId($event->identityId);
185
    }
186
187
    protected function applySelectRaaOptionChangedEvent(SelectRaaOptionChangedEvent $event)
188
    {
189
        $authorizedInstitutions = $event->selectRaaOption->getInstitutions($event->institution);
190
        $this->updateInstitutionCandidatesFromCollection(new Institution($event->institution->getInstitution()), $authorizedInstitutions);
191
    }
192
193
    protected function applyInstitutionConfigurationRemovedEvent(InstitutionConfigurationRemovedEvent $event)
194
    {
195
        $this->raCandidateRepository->removeByRaInstitution(new Institution($event->institution->getInstitution()));
196
    }
197
198
    /**
199
     * This method is kept to be backwards compatible for changes before FGA
200
     *
201
     * @param IdentityAccreditedAsRaEvent $event
202
     * @return void
203
     */
204
    public function applyIdentityAccreditedAsRaEvent(IdentityAccreditedAsRaEvent $event)
205
    {
206
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->identityInstitution);
207
    }
208
209
    /**
210
     * This method is kept to be backwards compatible for changes before FGA
211
     *
212
     * @param IdentityAccreditedAsRaaEvent $event
213
     * @return void
214
     */
215
    public function applyIdentityAccreditedAsRaaEvent(IdentityAccreditedAsRaaEvent $event)
216
    {
217
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->identityInstitution);
218
    }
219
220
    /**
221
     * This method is kept to be backwards compatible for changes before FGA
222
     *
223
     * @param RegistrationAuthorityRetractedEvent $event
224
     * @return void
225
     */
226 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...
227
    {
228
        $candidate = RaCandidate::nominate(
229
            $event->identityId,
230
            $event->identityInstitution,
231
            $event->nameId,
232
            $event->commonName,
233
            $event->email,
234
            $event->identityInstitution
235
        );
236
237
        $this->raCandidateRepository->merge($candidate);
238
    }
239
240
    /**
241
     * @param Institution $institution
242
     * @param ConfigurationInstitution[] $authorizedInstitutions
243
     * @throws \Doctrine\ORM\NonUniqueResultException
244
     */
245
    private function updateInstitutionCandidatesFromCollection(Institution $institution, array $authorizedInstitutions)
246
    {
247
        // convert configuration to value institutions
248
        $raInstitutions = new InstitutionCollection();
249
        foreach ($authorizedInstitutions as $authorizedInstitution) {
250
            $raInstitutions->add(new Institution($authorizedInstitution->getInstitution()));
251
        }
252
253
        // Remove candidates from removed institutions
254
        $this->raCandidateRepository->removeInstitutionsNotInList($institution, $raInstitutions);
255
256
        // loop through authorized institutions
257
        foreach ($raInstitutions as $raInstitution) {
258
            // add new identities
259
            $raSecondFactors = $this->raSecondFactorRepository->findByInstitution($raInstitution->getInstitution());
260
            foreach ($raSecondFactors as $raSecondFactor) {
261
                $identity = $this->identityRepository->find($raSecondFactor->identityId);
262
                $identityId = new IdentityId($identity->id);
263
264
                // check if persistent in ra listing
265
                if ($this->raListingRepository->findByIdentityIdAndRaInstitution($identityId, $institution)) {
266
                    continue;
267
                }
268
269
                // create candidate if not exists
270
                $candidate = $this->raCandidateRepository->findByIdentityIdAndRaInstitution($identityId, $institution);
271
                if (!$candidate) {
272
                    $candidate = RaCandidate::nominate(
273
                        $identityId,
274
                        $identity->institution,
275
                        $identity->nameId,
276
                        $identity->commonName,
277
                        $identity->email,
278
                        $institution
279
                    );
280
                }
281
282
                // store
283
                $this->raCandidateRepository->merge($candidate);
284
            }
285
        }
286
    }
287
288
    /**
289
     * @param Institution $identityInstitution
290
     * @param IdentityId $identityId
291
     * @param NameId $identityNameId
292
     * @param CommonName $identityCommonName
293
     * @param Email $identityEmail
294
     * @throws \Doctrine\ORM\NonUniqueResultException
295
     */
296
    private function addCandidateToProjection(
297
        Institution $identityInstitution,
298
        IdentityId $identityId,
299
        NameId $identityNameId,
300
        CommonName $identityCommonName,
301
        Email $identityEmail
302
    ) {
303
        $institutionAuthorizations = $this->institutionAuthorizationRepository
304
            ->findAuthorizationOptionsForInstitution(new ConfigurationInstitution($identityInstitution->getInstitution()));
305
306
        $institutions = [];
307
        foreach ($institutionAuthorizations as $authorization) {
308
            $raInstitutionName = $authorization->institutionRelation->getInstitution();
309
            $institutions[$raInstitutionName] = new Institution($raInstitutionName);
310
        }
311
312
        foreach ($institutions as $institution) {
313
            if ($this->raListingRepository->findByIdentityIdAndInstitution($identityId, $institution)) {
314
                continue;
315
            }
316
317
            // create candidate if not exists
318
            $candidate = $this->raCandidateRepository->findByIdentityIdAndRaInstitution($identityId, $institution);
319
            if (!$candidate) {
320
                $candidate = RaCandidate::nominate(
321
                    $identityId,
322
                    $identityInstitution,
323
                    $identityNameId,
324
                    $identityCommonName,
325
                    $identityEmail,
326
                    $institution
327
                );
328
            }
329
330
            $this->raCandidateRepository->merge($candidate);
331
        }
332
    }
333
}
334