Completed
Pull Request — feature/fine-grained-authoriza... (#249)
by Michiel
17:53 queued 15:17
created

RaCandidateProjector::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
c 0
b 0
f 0
rs 9.9
cc 1
nc 1
nop 4
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\Value\IdentityId;
30
use Surfnet\Stepup\Identity\Value\Institution;
31
use Surfnet\Stepup\Configuration\Value\Institution as ConfigurationInstitution;
32
use Surfnet\Stepup\Identity\Event\CompliedWithVettedSecondFactorRevocationEvent;
33
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaaEvent;
34
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaEvent;
35
use Surfnet\Stepup\Identity\Event\IdentityForgottenEvent;
36
use Surfnet\Stepup\Identity\Event\RegistrationAuthorityRetractedEvent;
37
use Surfnet\Stepup\Identity\Event\SecondFactorVettedEvent;
38
use Surfnet\Stepup\Identity\Event\VettedSecondFactorRevokedEvent;
39
use Surfnet\Stepup\Identity\Event\YubikeySecondFactorBootstrappedEvent;
40
use Surfnet\StepupMiddleware\ApiBundle\Configuration\Repository\InstitutionAuthorizationRepository;
41
use Surfnet\StepupMiddleware\ApiBundle\Identity\Entity\RaCandidate;
42
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\IdentityRepository;
43
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\RaCandidateRepository;
44
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\RaListingRepository;
45
46
/**
47
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
48
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
49
 */
50
class RaCandidateProjector extends Projector
51
{
52
    /**
53
     * @var RaCandidateRepository
54
     */
55
    private $raCandidateRepository;
56
57
    /**
58
     * @var RaListingRepository
59
     */
60
    private $raListingRepository;
61
62
    /**
63
     * @var institutionAuthorizationRepository
64
     */
65
    private $institutionAuthorizationRepository;
66
    /**
67
     * @var IdentityRepository
68
     */
69
    private $identityRepository;
70
71
    public function __construct(
72
        RaCandidateRepository $raCandidateRepository,
73
        RaListingRepository $raListingRepository,
74
        InstitutionAuthorizationRepository $institutionAuthorizationRepository,
75
        IdentityRepository $identityRepository
76
    ) {
77
        $this->raCandidateRepository = $raCandidateRepository;
78
        $this->raListingRepository = $raListingRepository;
79
        $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...
80
        $this->identityRepository = $identityRepository;
81
    }
82
83
    /**
84
     * @param SecondFactorVettedEvent $event
85
     * @return void
86
     */
87
    public function applySecondFactorVettedEvent(SecondFactorVettedEvent $event)
88
    {
89
        $institutionAuthorizations = $this->institutionAuthorizationRepository
90
            ->findAuthorizationOptionsForInstitution(new ConfigurationInstitution($event->identityInstitution->getInstitution()));
91
92
        $institutions = [];
93
        foreach ($institutionAuthorizations as $authorization) {
94
            $institutions[$authorization->institution->getInstitution()] = new Institution($authorization->institution->getInstitution());
95
        }
96
97 View Code Duplication
        foreach ($institutions as $institution) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
98
            if ($this->raListingRepository->findByIdentityIdAndInstitution($event->identityId, $institution)) {
99
                continue;
100
            }
101
102
            $candidate = RaCandidate::nominate(
103
                $event->identityId,
104
                $event->identityInstitution,
105
                $event->nameId,
106
                $event->commonName,
107
                $event->email,
108
                $institution
109
            );
110
111
            $this->raCandidateRepository->merge($candidate);
112
        }
113
    }
114
115
    /**
116
     * @param YubikeySecondFactorBootstrappedEvent $event
117
     * @return void
118
     */
119
    public function applyYubikeySecondFactorBootstrappedEvent(YubikeySecondFactorBootstrappedEvent $event)
120
    {
121
        $institutionAuthorizations = $this->institutionAuthorizationRepository
122
            ->findAuthorizationOptionsForInstitution(new ConfigurationInstitution($event->identityInstitution->getInstitution()));
123
124 View Code Duplication
        foreach ($institutionAuthorizations as $authorization) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
125
126
            $institution = new Institution($authorization->institution->getInstitution());
127
128
            $candidate = RaCandidate::nominate(
129
                $event->identityId,
130
                $event->identityInstitution,
131
                $event->nameId,
132
                $event->commonName,
133
                $event->email,
134
                $institution
135
            );
136
137
            $this->raCandidateRepository->merge($candidate);
138
        }
139
    }
140
141
    /**
142
     * @param VettedSecondFactorRevokedEvent $event
143
     * @return void
144
     */
145
    public function applyVettedSecondFactorRevokedEvent(VettedSecondFactorRevokedEvent $event)
146
    {
147
        $this->raCandidateRepository->removeByIdentityId($event->identityId);
148
    }
149
150
    /**
151
     * @param CompliedWithVettedSecondFactorRevocationEvent $event
152
     * @return void
153
     */
154
    public function applyCompliedWithVettedSecondFactorRevocationEvent(
155
        CompliedWithVettedSecondFactorRevocationEvent $event
156
    ) {
157
        $this->raCandidateRepository->removeByIdentityId($event->identityId);
158
    }
159
160
    /**
161
     * @param SraaUpdatedEvent $event
162
     *
163
     * Removes all RaCandidates that have a nameId matching an SRAA, as they cannot be made RA(A) as they
164
     * already are SRAA.
165
     */
166
    public function applySraaUpdatedEvent(SraaUpdatedEvent $event)
167
    {
168
        $this->raCandidateRepository->removeByNameIds($event->sraaList);
169
    }
170
171
    /**
172
     * @param IdentityAccreditedAsRaForInstitutionEvent $event
173
     * @return void
174
     */
175
    public function applyIdentityAccreditedAsRaForInstitutionEvent(IdentityAccreditedAsRaForInstitutionEvent $event)
176
    {
177
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->raInstitution);
178
    }
179
180
    /**
181
     * @param IdentityAccreditedAsRaaForInstitutionEvent $event
182
     * @return void
183
     */
184
    public function applyIdentityAccreditedAsRaaForInstitutionEvent(IdentityAccreditedAsRaaForInstitutionEvent $event)
185
    {
186
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->raInstitution);
187
    }
188
189
    /**
190
     * @param RegistrationAuthorityRetractedForInstitutionEvent $event
191
     * @return void
192
     */
193 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...
194
    {
195
        $candidate = RaCandidate::nominate(
196
            $event->identityId,
197
            $event->identityInstitution,
198
            $event->nameId,
199
            $event->commonName,
200
            $event->email,
201
            $event->raInstitution
202
        );
203
204
        $this->raCandidateRepository->merge($candidate);
205
    }
206
207
    protected function applyIdentityForgottenEvent(IdentityForgottenEvent $event)
208
    {
209
        $this->raCandidateRepository->removeByIdentityId($event->identityId);
210
    }
211
212
    protected function applySelectRaaOptionChangedEvent(SelectRaaOptionChangedEvent $event)
213
    {
214
        $authorizedInstitutions = $event->selectRaaOption->getInstitutions($event->institution);
215
        $this->updateInstitutionCandidatesFromCollection(new Institution($event->institution->getInstitution()), $authorizedInstitutions);
216
    }
217
218
    protected function applyInstitutionConfigurationRemovedEvent(InstitutionConfigurationRemovedEvent $event)
219
    {
220
        $this->raCandidateRepository->removeByRaInstitution(new Institution($event->institution->getInstitution()));
221
    }
222
223
    /**
224
     * This method is kept to be backwards compatible for changes before FGA
225
     *
226
     * @param IdentityAccreditedAsRaEvent $event
227
     * @return void
228
     */
229
    public function applyIdentityAccreditedAsRaEvent(IdentityAccreditedAsRaEvent $event)
230
    {
231
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->identityInstitution);
232
    }
233
234
    /**
235
     * This method is kept to be backwards compatible for changes before FGA
236
     *
237
     * @param IdentityAccreditedAsRaaEvent $event
238
     * @return void
239
     */
240
    public function applyIdentityAccreditedAsRaaEvent(IdentityAccreditedAsRaaEvent $event)
241
    {
242
        $this->raCandidateRepository->removeByIdentityIdAndRaInstitution($event->identityId, $event->identityInstitution);
243
    }
244
245
    /**
246
     * This method is kept to be backwards compatible for changes before FGA
247
     *
248
     * @param RegistrationAuthorityRetractedEvent $event
249
     * @return void
250
     */
251 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...
252
    {
253
        $candidate = RaCandidate::nominate(
254
            $event->identityId,
255
            $event->identityInstitution,
256
            $event->nameId,
257
            $event->commonName,
258
            $event->email,
259
            $event->raInstitution
0 ignored issues
show
Bug introduced by
The property raInstitution does not seem to exist in Surfnet\Stepup\Identity\...AuthorityRetractedEvent.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
260
        );
261
262
        $this->raCandidateRepository->merge($candidate);
263
    }
264
265
    /**
266
     * @param Institution $institution
267
     * @param ConfigurationInstitution[] $authorizedInstitutions
268
     * @throws \Doctrine\ORM\NonUniqueResultException
269
     */
270
    private function updateInstitutionCandidatesFromCollection(Institution $institution, array $authorizedInstitutions)
271
    {
272
        // convert configuration to value institutions
273
        $raInstitutions = new InstitutionCollection();
274
        foreach ($authorizedInstitutions as $authorizedInstitution) {
275
            $raInstitutions->add(new Institution($authorizedInstitution->getInstitution()));
276
        }
277
278
        // Remove candidates from removed institutions
279
        $this->raCandidateRepository->removeInstitutionsNotInList($institution, $raInstitutions);
280
281
        // loop through authorized institutions
282
        foreach ($raInstitutions as $raInstitution) {
283
284
            // add new identities
285
            $identities = $this->identityRepository->findByInstitution($raInstitution);
286
            foreach ($identities as $identity) {
287
                $identityId = new IdentityId($identity->id);
288
289
                // check if persistent in ra listing
290
                if ($this->raListingRepository->findByIdentityIdAndInstitution($identityId, $raInstitution)) {
291
                    continue;
292
                }
293
294
                // create candidate if not exists
295
                $candidate = $this->raCandidateRepository->findByIdentityIdAndRaInstitution($identityId, $raInstitution);
296
                if (!$candidate) {
297
                    $candidate = RaCandidate::nominate(
298
                        $identityId,
299
                        $identity->institution,
300
                        $identity->nameId,
301
                        $identity->commonName,
302
                        $identity->email,
303
                        $institution
304
                    );
305
                }
306
307
                // store
308
                $this->raCandidateRepository->merge($candidate);
309
            }
310
        }
311
    }
312
}
313