RaSecondFactorRepository::findByInstitution()   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
 */
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>
39
 */
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 */
52
        $secondFactor = parent::find($id);
53
54
        return $secondFactor;
55
    }
56
57
    /**
58
     * @return RaSecondFactor[]
59
     */
60
    public function findByIdentityId(string $identityId): array
61
    {
62
        return parent::findBy(['identityId' => $identityId]);
63
    }
64
65
66
    /**
67
     * @return RaSecondFactor[]
68
     */
69
    public function findByInstitution(string $institution): array
70
    {
71
        return parent::findBy(['institution' => $institution]);
72
    }
73
74
    /**
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
     */
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
    /**
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
    /**
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
     */
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