Completed
Push — feature/self-vet ( 66ee82...7edffb )
by Michiel
03:58
created

AuditLogProjector::applyAuditableEvent()   C

Complexity

Conditions 10
Paths 129

Size

Total Lines 54

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 54
rs 6.9436
c 0
b 0
f 0
cc 10
nc 129
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Domain\DomainMessage;
22
use Broadway\EventHandling\EventListener;
23
use DateTime as CoreDateTime;
24
use Rhumsaa\Uuid\Uuid;
25
use Surfnet\Stepup\DateTime\DateTime;
26
use Surfnet\Stepup\Identity\Event\AuditableEvent;
27
use Surfnet\Stepup\Identity\Event\IdentityForgottenEvent;
28
use Surfnet\Stepup\Identity\Event\SecondFactorVettedEvent;
29
use Surfnet\Stepup\Identity\Event\SecondFactorVettedWithoutTokenProofOfPossession;
30
use Surfnet\Stepup\Identity\Value\CommonName;
31
use Surfnet\Stepup\Identity\Value\VettingType;
32
use Surfnet\StepupMiddleware\ApiBundle\Exception\RuntimeException;
33
use Surfnet\StepupMiddleware\ApiBundle\Identity\Entity\AuditLogEntry;
34
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\AuditLogRepository;
35
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\IdentityRepository;
36
37
class AuditLogProjector implements EventListener
38
{
39
    /**
40
     * @var \Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\AuditLogRepository
41
     */
42
    private $auditLogRepository;
43
44
    /**
45
     * @var \Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\IdentityRepository
46
     */
47
    private $identityRepository;
48
49
    public function __construct(
50
        AuditLogRepository $auditLogRepository,
51
        IdentityRepository $identityRepository
52
    ) {
53
        $this->auditLogRepository = $auditLogRepository;
54
        $this->identityRepository = $identityRepository;
55
    }
56
57
    /**
58
     * @param DomainMessage $domainMessage
59
     */
60
    public function handle(DomainMessage $domainMessage): void
61
    {
62
        $event = $domainMessage->getPayload();
63
64
        if ($event instanceof IdentityForgottenEvent) {
65
            // Don't insert the IdentityForgottenEvent into the audit log, as we'd remove it immediately afterwards.
66
            $this->applyIdentityForgottenEvent($event);
67
        } elseif ($event instanceof AuditableEvent) {
68
            $this->applyAuditableEvent($event, $domainMessage);
69
        }
70
    }
71
72
    /**
73
     * @param AuditableEvent $event
74
     * @param DomainMessage  $domainMessage
75
     */
76
    private function applyAuditableEvent(AuditableEvent $event, DomainMessage $domainMessage)
77
    {
78
        $auditLogMetadata = $event->getAuditLogMetadata();
79
        $metadata = $domainMessage->getMetadata()->serialize();
80
81
        $entry = new AuditLogEntry();
82
        $entry->id = (string) Uuid::uuid4();
83
84
        if (isset($metadata['actorId'])) {
85
            $actor = $this->identityRepository->find($metadata['actorId']);
86
87
            if (!$actor) {
88
                throw new RuntimeException(sprintf(
89
                    'Cannot create AuditLogEntry, given Actor Identity "%s" does not exist',
90
                    $metadata['actorId']
91
                ));
92
            }
93
94
            $entry->actorId         = $metadata['actorId'];
95
            $entry->actorCommonName = $actor->commonName;
96
        }
97
        if ($event instanceof SecondFactorVettedEvent ||
98
            $event instanceof SecondFactorVettedWithoutTokenProofOfPossession
99
        ) {
100
            $entry->actorCommonName .= $event->vettingType->auditLog();
101
        }
102
103
        if (isset($metadata['actorInstitution'])) {
104
            $entry->actorInstitution = $metadata['actorInstitution'];
105
        }
106
107
        $entry->identityId          = (string) $auditLogMetadata->identityId;
108
        $entry->identityInstitution = $auditLogMetadata->identityInstitution;
109
        $entry->event               = get_class($event);
110
        $entry->recordedOn          = new DateTime(new CoreDateTime($domainMessage->getRecordedOn()->toString()));
111
112
        if ($auditLogMetadata->secondFactorId) {
113
            $entry->secondFactorId = (string) $auditLogMetadata->secondFactorId;
114
        }
115
116
        if ($auditLogMetadata->secondFactorType) {
117
            $entry->secondFactorType = (string) $auditLogMetadata->secondFactorType;
118
        }
119
120
        if ($auditLogMetadata->secondFactorIdentifier) {
121
            $entry->secondFactorIdentifier = (string) $auditLogMetadata->secondFactorIdentifier;
122
        }
123
124
        if ($auditLogMetadata->raInstitution) {
125
            $entry->raInstitution = (string) $auditLogMetadata->raInstitution;
126
        }
127
128
        $this->auditLogRepository->save($entry);
129
    }
130
131
    private function applyIdentityForgottenEvent(IdentityForgottenEvent $event)
132
    {
133
        $entriesWhereActor = $this->auditLogRepository->findEntriesWhereIdentityIsActorOnly($event->identityId);
134
        foreach ($entriesWhereActor as $auditLogEntry) {
135
            $auditLogEntry->actorCommonName = CommonName::unknown();
136
        }
137
138
        $this->auditLogRepository->saveAll($entriesWhereActor);
139
        $this->auditLogRepository->removeByIdentityId($event->identityId);
140
    }
141
}
142