RaSecondFactorRepository::findByIdentityId()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
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
 */
0 ignored issues
show
Coding Style introduced by
Missing @link tag in file comment
Loading history...
18
19
namespace Surfnet\StepupMiddleware\ApiBundle\Identity\Repository;
20
21
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
22
use Doctrine\DBAL\Types\Type;
23
use Doctrine\ORM\Query;
24
use Doctrine\Persistence\ManagerRegistry;
25
use Surfnet\Stepup\Exception\RuntimeException;
26
use Surfnet\Stepup\Identity\Value\CommonName;
27
use Surfnet\Stepup\Identity\Value\DocumentNumber;
28
use Surfnet\Stepup\Identity\Value\Email;
29
use Surfnet\Stepup\Identity\Value\IdentityId;
30
use Surfnet\StepupMiddleware\ApiBundle\Authorization\Filter\InstitutionAuthorizationRepositoryFilter;
31
use Surfnet\StepupMiddleware\ApiBundle\Doctrine\Type\SecondFactorStatusType;
32
use Surfnet\StepupMiddleware\ApiBundle\Identity\Entity\RaSecondFactor;
33
use Surfnet\StepupMiddleware\ApiBundle\Identity\Query\RaSecondFactorQuery;
34
use Surfnet\StepupMiddleware\ApiBundle\Identity\Value\SecondFactorStatus;
0 ignored issues
show
Bug introduced by
The type Surfnet\StepupMiddleware...alue\SecondFactorStatus was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
35
36
/**
37
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
38
 * @extends ServiceEntityRepository<RaSecondFactor>
0 ignored issues
show
Coding Style introduced by
Tag value for @extends tag indented incorrectly; expected 40 spaces but found 1
Loading history...
39
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
40
class RaSecondFactorRepository extends ServiceEntityRepository
41
{
42
    public function __construct(
43
        ManagerRegistry $registry,
44
        private readonly InstitutionAuthorizationRepositoryFilter $authorizationRepositoryFilter,
45
    ) {
46
        parent::__construct($registry, RaSecondFactor::class);
47
    }
48
49
    public function find(mixed $id, $lockMode = null, $lockVersion = null): ?RaSecondFactor
50
    {
51
        /** @var RaSecondFactor|null $secondFactor */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
52
        $secondFactor = parent::find($id);
53
54
        return $secondFactor;
55
    }
56
57
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $identityId should have a doc-comment as per coding-style.
Loading history...
58
     * @return RaSecondFactor[]
59
     */
60
    public function findByIdentityId(string $identityId): array
61
    {
62
        return parent::findBy(['identityId' => $identityId]);
63
    }
64
65
66
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $institution should have a doc-comment as per coding-style.
Loading history...
67
     * @return RaSecondFactor[]
68
     */
69
    public function findByInstitution(string $institution): array
70
    {
71
        return parent::findBy(['institution' => $institution]);
72
    }
73
74
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $query should have a doc-comment as per coding-style.
Loading history...
75
     * @SuppressWarnings(PHPMD.CyclomaticComplexity) The amount of if statements do not necessarily make the method
76
     *                                               below complex or hard to maintain.
77
     * @SuppressWarnings(PHPMD.NPathComplexity)
78
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
79
    public function createSearchQuery(RaSecondFactorQuery $query): Query
80
    {
81
        $queryBuilder = $this
82
            ->createQueryBuilder('sf');
83
84
        // Modify query to filter on authorization context
85
        // We want to list all second factors of the institution we are RA for.
86
        $this->authorizationRepositoryFilter->filter(
87
            $queryBuilder,
88
            $query->authorizationContext,
89
            'sf.institution',
90
            'iac',
91
        );
92
93
        if ($query->name) {
94
            $queryBuilder->andWhere('sf.name LIKE :name')->setParameter('name', sprintf('%%%s%%', $query->name));
95
        }
96
97
        if ($query->type) {
98
            $queryBuilder->andWhere('sf.type = :type')->setParameter('type', $query->type);
99
        }
100
101
        if ($query->secondFactorId) {
102
            $queryBuilder
103
                ->andWhere('sf.secondFactorId = :secondFactorId')
104
                ->setParameter('secondFactorId', $query->secondFactorId);
105
        }
106
107
        if ($query->email) {
108
            $queryBuilder->andWhere('sf.email LIKE :email')->setParameter('email', sprintf('%%%s%%', $query->email));
109
        }
110
111
        if ($query->institution) {
112
            $queryBuilder->andWhere('sf.institution = :institution')->setParameter('institution', $query->institution);
113
        }
114
115
        if ($query->status) {
116
            $stringStatus = $query->status;
117
            if (!SecondFactorStatus::isValidStatus($stringStatus)) {
118
                throw new RuntimeException(
119
                    sprintf(
120
                        'Received invalid status "%s" in RaSecondFactorRepository::createSearchQuery',
121
                        $stringStatus,
122
                    ),
123
                );
124
            }
125
126
            // we need to resolve the string value to database value using the correct doctrine type. Normally this is
127
            // done by doctrine itself, however the queries PagerFanta creates somehow manages to mangle this...
128
            // so we do it by hand
129
            $doctrineType = Type::getType(SecondFactorStatusType::NAME);
130
            $secondFactorStatus = SecondFactorStatus::$stringStatus();
131
132
            $databaseValue = $doctrineType->convertToDatabaseValue(
133
                $secondFactorStatus,
134
                $this->getEntityManager()->getConnection()->getDatabasePlatform(),
135
            );
136
137
            $queryBuilder->andWhere('sf.status = :status')->setParameter('status', $databaseValue);
138
        }
139
140
        match ($query->orderBy) {
141
            'name', 'type', 'secondFactorId', 'email', 'institution', 'status' => $queryBuilder->orderBy(
142
                sprintf('sf.%s', $query->orderBy),
143
                $query->orderDirection === 'desc' ? 'DESC' : 'ASC',
144
            ),
145
            default => $queryBuilder->getQuery(),
146
        };
147
148
        return $queryBuilder->getQuery();
149
    }
150
151
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $query should have a doc-comment as per coding-style.
Loading history...
152
     * @return Query
153
     */
154
    public function createOptionsQuery(RaSecondFactorQuery $query): Query
155
    {
156
        $queryBuilder = $this->createQueryBuilder('sf')
157
            ->select('sf.institution')
158
            ->groupBy('sf.institution');
159
160
        // Modify query to filter on authorization context
161
        // We want to list all second factors of the institution we are RA for.
162
        $this->authorizationRepositoryFilter->filter(
163
            $queryBuilder,
164
            $query->authorizationContext,
165
            'sf.institution',
166
            'iac',
167
        );
168
169
        return $queryBuilder->getQuery();
170
    }
171
172
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $identityId should have a doc-comment as per coding-style.
Loading history...
173
     * @return void
174
     */
175
    public function removeByIdentityId(IdentityId $identityId): void
176
    {
177
        $this->getEntityManager()->createQueryBuilder()
178
            ->delete($this->getEntityName(), 'rasf')
179
            ->where('rasf.identityId = :identityId')
180
            ->setParameter('identityId', $identityId->getIdentityId())
181
            ->getQuery()
182
            ->execute();
183
    }
184
185
    public function save(RaSecondFactor $secondFactor): void
186
    {
187
        $this->getEntityManager()->persist($secondFactor);
188
        $this->getEntityManager()->flush();
189
    }
190
191
    /**
192
     * @param RaSecondFactor[] $secondFactors
193
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
194
    public function saveAll(array $secondFactors): void
195
    {
196
        $entityManager = $this->getEntityManager();
197
198
        foreach ($secondFactors as $secondFactor) {
199
            $entityManager->persist($secondFactor);
200
        }
201
202
        $entityManager->flush();
203
    }
204
205
    public function updateStatusByIdentityIdToForgotten(IdentityId $identityId): void
206
    {
207
        $this->getEntityManager()->createQueryBuilder()
208
            ->update($this->getEntityName(), 'rasf')
209
            ->set('rasf.status', ":forgotten")
210
            ->set('rasf.name', ":name")
211
            ->set('rasf.email', ":email")
212
            ->set('rasf.documentNumber', ":documentNumber")
213
            ->where('rasf.identityId = :identityId')
214
            ->setParameter('identityId', $identityId->getIdentityId())
215
            ->setParameter('forgotten', 40)
216
            ->setParameter('name', CommonName::unknown())
217
            ->setParameter('email', Email::unknown())
218
            ->setParameter('documentNumber', DocumentNumber::unknown())
219
            ->getQuery()
220
            ->execute();
221
    }
222
}
223