Completed
Push — feature/fix-token-ra-candiate-... ( 2911b4 )
by
unknown
03:26
created

applyVettedSecondFactorRevokedEvent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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