AuditLogEntry   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 132
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 90
dl 0
loc 132
rs 10
c 0
b 0
f 0
wmc 5

2 Methods

Rating   Name   Duplication   Size   Complexity  
A mapEventToAction() 0 7 2
A jsonSerialize() 0 16 3
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\Entity;
20
21
use Doctrine\ORM\Mapping as ORM;
22
use JsonSerializable;
23
use Surfnet\Stepup\DateTime\DateTime;
24
use Surfnet\Stepup\Identity\Event\AppointedAsRaaEvent;
25
use Surfnet\Stepup\Identity\Event\AppointedAsRaaForInstitutionEvent;
26
use Surfnet\Stepup\Identity\Event\AppointedAsRaEvent;
27
use Surfnet\Stepup\Identity\Event\AppointedAsRaForInstitutionEvent;
28
use Surfnet\Stepup\Identity\Event\CompliedWithRecoveryCodeRevocationEvent;
29
use Surfnet\Stepup\Identity\Event\CompliedWithUnverifiedSecondFactorRevocationEvent;
30
use Surfnet\Stepup\Identity\Event\CompliedWithVerifiedSecondFactorRevocationEvent;
31
use Surfnet\Stepup\Identity\Event\CompliedWithVettedSecondFactorRevocationEvent;
32
use Surfnet\Stepup\Identity\Event\EmailVerifiedEvent;
33
use Surfnet\Stepup\Identity\Event\GssfPossessionProvenAndVerifiedEvent;
34
use Surfnet\Stepup\Identity\Event\GssfPossessionProvenEvent;
35
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaaEvent;
36
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaaForInstitutionEvent;
37
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaEvent;
38
use Surfnet\Stepup\Identity\Event\IdentityAccreditedAsRaForInstitutionEvent;
39
use Surfnet\Stepup\Identity\Event\IdentityCreatedEvent;
40
use Surfnet\Stepup\Identity\Event\IdentityEmailChangedEvent;
41
use Surfnet\Stepup\Identity\Event\IdentityRenamedEvent;
42
use Surfnet\Stepup\Identity\Event\PhonePossessionProvenAndVerifiedEvent;
43
use Surfnet\Stepup\Identity\Event\PhonePossessionProvenEvent;
44
use Surfnet\Stepup\Identity\Event\PhoneRecoveryTokenPossessionProvenEvent;
45
use Surfnet\Stepup\Identity\Event\RecoveryTokenRevokedEvent;
46
use Surfnet\Stepup\Identity\Event\RegistrationAuthorityRetractedEvent;
47
use Surfnet\Stepup\Identity\Event\RegistrationAuthorityRetractedForInstitutionEvent;
48
use Surfnet\Stepup\Identity\Event\SafeStoreSecretRecoveryTokenPossessionPromisedEvent;
49
use Surfnet\Stepup\Identity\Event\SecondFactorMigratedEvent;
50
use Surfnet\Stepup\Identity\Event\SecondFactorMigratedToEvent;
51
use Surfnet\Stepup\Identity\Event\SecondFactorVettedEvent;
52
use Surfnet\Stepup\Identity\Event\SecondFactorVettedWithoutTokenProofOfPossession;
53
use Surfnet\Stepup\Identity\Event\UnverifiedSecondFactorRevokedEvent;
54
use Surfnet\Stepup\Identity\Event\VerifiedSecondFactorRevokedEvent;
55
use Surfnet\Stepup\Identity\Event\VettedSecondFactorRevokedEvent;
56
use Surfnet\Stepup\Identity\Event\YubikeyPossessionProvenAndVerifiedEvent;
57
use Surfnet\Stepup\Identity\Event\YubikeyPossessionProvenEvent;
58
use Surfnet\Stepup\Identity\Event\YubikeySecondFactorBootstrappedEvent;
59
use Surfnet\Stepup\Identity\Value\CommonName;
60
use Surfnet\Stepup\Identity\Value\Institution;
61
use Surfnet\StepupMiddleware\ApiBundle\Exception\LogicException;
62
use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\AuditLogRepository;
63
64
/**
65
 * @SuppressWarnings("PHPMD.UnusedPrivateField")
66
 */
67
#[ORM\Table(name: 'audit_log')]
68
#[ORM\Index(name: 'idx_auditlog_actorid', columns: ['actor_id'])]
69
#[ORM\Index(name: 'idx_auditlog_identityid', columns: ['identity_id'])]
70
#[ORM\Index(name: 'idx_auditlog_identityinstitution', columns: ['identity_institution'])]
71
#[ORM\Index(name: 'idx_auditlog_secondfactorid', columns: ['second_factor_id'])]
72
#[ORM\Index(name: 'idx_auditlog_ra_institution', columns: ['ra_institution'])]
73
#[ORM\Entity(repositoryClass: AuditLogRepository::class)]
74
class AuditLogEntry implements JsonSerializable
75
{
76
    /**
77
     * Maps event FQCNs to action names.
78
     *
79
     * @var string[]
80
     */
81
    private array $eventActionMap = [
82
        CompliedWithUnverifiedSecondFactorRevocationEvent::class => 'revoked_by_ra',
83
        CompliedWithVerifiedSecondFactorRevocationEvent::class => 'revoked_by_ra',
84
        CompliedWithVettedSecondFactorRevocationEvent::class => 'revoked_by_ra',
85
        EmailVerifiedEvent::class => 'email_verified',
86
        GssfPossessionProvenEvent::class => 'possession_proven',
87
        GssfPossessionProvenAndVerifiedEvent::class => 'possession_proven',
88
        IdentityCreatedEvent::class => 'created',
89
        IdentityEmailChangedEvent::class => 'email_changed',
90
        IdentityRenamedEvent::class => 'renamed',
91
        PhonePossessionProvenEvent::class => 'possession_proven',
92
        PhonePossessionProvenAndVerifiedEvent::class => 'possession_proven',
93
        SecondFactorVettedEvent::class => 'vetted',
94
        SecondFactorVettedWithoutTokenProofOfPossession::class => 'vetted_possession_unknown',
95
        SecondFactorMigratedToEvent::class => 'migrated_to',
96
        SecondFactorMigratedEvent::class => 'migrated_from',
97
        UnverifiedSecondFactorRevokedEvent::class => 'revoked',
98
        VerifiedSecondFactorRevokedEvent::class => 'revoked',
99
        VettedSecondFactorRevokedEvent::class => 'revoked',
100
        YubikeyPossessionProvenEvent::class => 'possession_proven',
101
        YubikeyPossessionProvenAndVerifiedEvent::class => 'possession_proven',
102
        YubikeySecondFactorBootstrappedEvent::class => 'bootstrapped',
103
        IdentityAccreditedAsRaaEvent::class => 'accredited_as_raa',
104
        IdentityAccreditedAsRaEvent::class => 'accredited_as_ra',
105
        IdentityAccreditedAsRaForInstitutionEvent::class => 'accredited_as_ra',
106
        IdentityAccreditedAsRaaForInstitutionEvent::class => 'accredited_as_raa',
107
        AppointedAsRaaEvent::class => 'appointed_as_raa',
108
        AppointedAsRaEvent::class => 'appointed_as_ra',
109
        AppointedAsRaaForInstitutionEvent::class => 'appointed_as_raa',
110
        AppointedAsRaForInstitutionEvent::class => 'appointed_as_ra',
111
        RegistrationAuthorityRetractedEvent::class => 'retracted_as_ra',
112
        RegistrationAuthorityRetractedForInstitutionEvent::class => 'retracted_as_ra',
113
        SafeStoreSecretRecoveryTokenPossessionPromisedEvent::class => 'recovery_token_possession_promised',
114
        RecoveryTokenRevokedEvent::class => 'recovery_token_revoked',
115
        PhoneRecoveryTokenPossessionProvenEvent::class => 'recovery_token_possession_proven',
116
        CompliedWithRecoveryCodeRevocationEvent::class => 'recovery_token_revoked',
117
    ];
118
119
    #[ORM\Id]
120
    #[ORM\Column(length: 36)]
121
    public string $id;
122
123
    #[ORM\Column(length: 36, nullable: true)]
124
    public ?string $actorId = null;
125
126
    #[ORM\Column(type: 'stepup_common_name', nullable: true)]
127
    public ?CommonName $actorCommonName = null;
128
129
    #[ORM\Column(type: 'institution', nullable: true)]
130
    public ?Institution $actorInstitution = null;
131
132
    /**
133
     * Only in certain situations will this field be filled, It represents the RA institution the
134
     * event log entry is targeted at. For example. John Doe is accredited to become RA by Joe from
135
     * institution-a. The actual institution John is appointed RA for is stored in this field.
136
     */
137
    #[ORM\Column(length: 255, nullable: true)]
138
    public ?string $raInstitution = null;
139
140
    #[ORM\Column(length: 36)]
141
    public string $identityId;
142
143
    #[ORM\Column(type: 'institution')]
144
    public Institution $identityInstitution;
145
146
    #[ORM\Column(length: 36, nullable: true)]
147
    public ?string $secondFactorId = null;
148
149
    #[ORM\Column(length: 255, nullable: true)]
150
    public ?string $secondFactorIdentifier = null;
151
152
    #[ORM\Column(length: 36, nullable: true)]
153
    public ?string $secondFactorType = null;
154
155
    #[ORM\Column(length: 255, nullable: true)]
156
    public ?string $recoveryTokenIdentifier = null;
157
158
    #[ORM\Column(length: 36, nullable: true)]
159
    public ?string $recoveryTokenType = null;
160
161
    #[ORM\Column(length: 255)]
162
    public string $event;
163
164
    #[ORM\Column(type: 'stepup_datetime')]
165
    public DateTime $recordedOn;
166
167
    public function jsonSerialize(): array
168
    {
169
        return [
170
            'actor_id' => $this->actorId,
171
            'actor_institution' => $this->actorInstitution instanceof Institution ? (string)$this->actorInstitution : null,
172
            'actor_common_name' => (string)$this->actorCommonName,
173
            'identity_id' => $this->identityId,
174
            'identity_institution' => (string)$this->identityInstitution,
175
            'ra_institution' => (string)$this->raInstitution,
176
            'second_factor_id' => $this->secondFactorId,
177
            'second_factor_type' => $this->secondFactorType ?: null,
178
            'second_factor_identifier' => $this->secondFactorIdentifier,
179
            'recovery_token_type' => $this->recoveryTokenType,
180
            'recovery_token_identifier' => $this->recoveryTokenIdentifier,
181
            'action' => $this->mapEventToAction($this->event),
182
            'recorded_on' => (string)$this->recordedOn,
183
        ];
184
    }
185
186
    /**
187
     * Maps an event FQCN to an action name (eg. '...\Event\IdentityCreatedEvent' to 'created').
188
     *
189
     * @param string $event Event FQCN
190
     * @return string Action name
191
     */
192
    private function mapEventToAction(string $event): string
193
    {
194
        if (!isset($this->eventActionMap[$event])) {
195
            throw new LogicException(sprintf("Action name for event '%s' not registered", $event));
196
        }
197
198
        return $this->eventActionMap[$event];
199
    }
200
}
201