Passed
Push — feature/main-authz-bugfix ( e03212 )
by Michiel
15:54 queued 09:38
created

AuthorizationRepository   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 86
c 1
b 0
f 0
dl 0
loc 165
rs 10
wmc 16

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getInstitutionsForSelectRaaRole() 0 31 2
A getInstitutionsForRole() 0 65 4
A __construct() 0 4 1
A getAllowedInstitutionRoles() 0 9 3
A getAllowedIdentityRoles() 0 9 3
A getInstitutionRoleByRaRole() 0 7 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
 */
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\Common\Persistence\ManagerRegistry;
23
use Doctrine\ORM\Query\Expr\Join;
24
use Psr\Log\LoggerInterface;
25
use Surfnet\Stepup\Configuration\Value\InstitutionRole;
26
use Surfnet\Stepup\Identity\Collection\InstitutionCollection;
27
use Surfnet\Stepup\Identity\Value\IdentityId;
28
use Surfnet\Stepup\Identity\Value\Institution;
29
use Surfnet\Stepup\Identity\Value\RegistrationAuthorityRole;
30
use Surfnet\StepupMiddleware\ApiBundle\Configuration\Entity\ConfiguredInstitution;
31
use Surfnet\StepupMiddleware\ApiBundle\Configuration\Entity\InstitutionAuthorization;
32
use Surfnet\StepupMiddleware\ApiBundle\Identity\Entity\AuditLogEntry;
33
use Surfnet\StepupMiddleware\ApiBundle\Identity\Entity\Identity;
34
use Surfnet\StepupMiddleware\ApiBundle\Identity\Entity\RaListing;
35
use Surfnet\StepupMiddleware\ApiBundle\Identity\Value\AuthorityRole;
36
37
/**
38
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
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 AuthorizationRepository extends ServiceEntityRepository
41
{
42
    /**
43
     * @var LoggerInterface
44
     */
45
    private $logger;
46
47
    public function __construct(ManagerRegistry $registry, LoggerInterface $logger)
48
    {
49
        parent::__construct($registry, AuditLogEntry::class);
50
        $this->logger = $logger;
51
    }
52
53
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $role should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $actorId should have a doc-comment as per coding-style.
Loading history...
54
     * Return all institutions were the actor has the specified role for
55
     * The returned institutions are used to filter query results on
56
     *
57
     * @return InstitutionCollection
58
     */
59
    public function getInstitutionsForRole(RegistrationAuthorityRole $role, IdentityId $actorId) :InstitutionCollection
60
    {
61
        $result = new InstitutionCollection();
62
        $qb = $this->_em->createQueryBuilder()
63
            ->select("a.institution")
64
            ->from(ConfiguredInstitution::class, 'i')
65
            ->innerJoin(RaListing::class, 'r', Join::WITH, "i.institution = r.raInstitution")
66
            ->innerJoin(
67
                InstitutionAuthorization::class,
68
                'a',
69
                Join::WITH,
70
                "i.institution = a.institutionRelation AND a.institutionRole IN (:authorizationRoles)"
71
            )
72
            ->where("r.identityId = :identityId AND r.role IN(:roles)")
73
            ->groupBy("a.institution");
74
75
        $qb->setParameter('identityId', (string)$actorId);
76
        $qb->setParameter(
77
            'authorizationRoles',
78
            $this->getAllowedInstitutionRoles($role)
79
        );
80
        $identityRoles = $this->getAllowedIdentityRoles($role);
81
        $qb->setParameter(
82
            'roles',
83
            $identityRoles
84
        );
85
86
        $institutions = $qb->getQuery()->getArrayResult();
87
        foreach ($institutions as $institution) {
88
            $this->logger->notice(
89
                sprintf('Adding %s to authorized institutions', $institution['institution'])
90
            );
91
            $result->add(new Institution((string)$institution['institution']));
92
        }
93
94
        // Also get the institutions that are linked to the user via the 'institution_relation' field.
95
        // Effectively getting the use_raa relation.
96
        // See https://www.pivotaltracker.com/story/show/181537313
97
        $qb = $this->_em->createQueryBuilder()
98
            ->select('ia.institution')
99
            ->from(InstitutionAuthorization::class, 'ia')
100
            // Filter the RA listing on the authorizations that apply for the RA(A) listed there
101
            // For example, when testing a USE_RA institution authorization, the listed RA should have
102
            // at least a RA or RAA role
103
            ->join(RaListing::class, 'r', Join::WITH, 'r.raInstitution = ia.institutionRelation AND r.role IN (:identityRoles)')
104
            ->where('r.identityId = :identityId')
105
            ->andWhere("ia.institutionRole = :role") // Only filter on use_ra and use_raa roles here.
106
            ->groupBy('ia.institution');
107
108
        $qb->setParameter('identityId', (string)$actorId);
109
        $qb->setParameter('role', $this->getInstitutionRoleByRaRole($role));
110
        $qb->setParameter('identityRoles', $identityRoles);
111
112
        $institutions = $qb->getQuery()->getArrayResult();
113
        foreach ($institutions as $institution) {
114
            $institutionVo = new Institution((string)$institution['institution']);
115
            if (!$result->contains($institutionVo)) {
116
                $result->add($institutionVo);
117
                $this->logger->notice(
118
                    sprintf('Adding %s to authorized institutions from %s', $role->getType(), $institution['institution'])
0 ignored issues
show
Bug introduced by
The method getType() does not exist on Surfnet\Stepup\Identity\...gistrationAuthorityRole. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

118
                    sprintf('Adding %s to authorized institutions from %s', $role->/** @scrutinizer ignore-call */ getType(), $institution['institution'])

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
119
                );
120
            }
121
        }
122
123
        return $result;
124
    }
125
126
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $actorId should have a doc-comment as per coding-style.
Loading history...
127
     * Finds the institutions that have the Select RAA authorization based on
128
     * the institution of the specified identity.
129
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
130
    public function getInstitutionsForSelectRaaRole(IdentityId $actorId)
131
    {
132
        $qb = $this->_em->createQueryBuilder()
133
            ->select("ci.institution")
134
            ->from(InstitutionAuthorization::class, 'ia')
135
            ->innerJoin(ConfiguredInstitution::class, 'ci', Join::WITH, 'ia.institutionRelation = ci.institution')
136
            ->innerJoin(Identity::class, 'i', Join::WITH, 'ia.institution = i.institution AND i.id = :identityId')
137
            ->innerJoin(RaListing::class, 'ra', Join::WITH, 'i.id = ra.identityId AND ra.role = :authorizationRole')
138
            ->where('ia.institutionRole = :institutionRole AND ra.role = :authorizationRole')
139
            ->groupBy("ci.institution");
140
141
        $qb->setParameter('identityId', (string)$actorId);
142
        // The identity requires RAA role to perform this search
143
        $qb->setParameter(
144
            'authorizationRole',
145
            AuthorityRole::ROLE_RAA
146
        );
147
        // Filter on the SELECT_RAA authorization in the institution authorization projection
148
        $qb->setParameter(
149
            'institutionRole',
150
            InstitutionRole::ROLE_SELECT_RAA
151
        );
152
153
        $institutions = $qb->getQuery()->getArrayResult();
154
155
        $result = new InstitutionCollection();
156
        foreach ($institutions as $institution) {
157
            $result->add(new Institution((string)$institution['institution']));
158
        }
159
160
        return $result;
161
    }
162
163
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $role should have a doc-comment as per coding-style.
Loading history...
164
     * This is the mapping to look up allowed institution roles
165
     * - if the required role is RA we should look if the configured institution has USE_RA role
166
     * - if the required role is RAA we should look if the configured institution has USE_RAA role
167
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
168
    private function getAllowedInstitutionRoles(RegistrationAuthorityRole $role): array
0 ignored issues
show
Coding Style introduced by
Private method name "AuthorizationRepository::getAllowedInstitutionRoles" must be prefixed with an underscore
Loading history...
169
    {
170
        switch (true) {
171
            case $role->equals(RegistrationAuthorityRole::ra()):
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
172
                return [InstitutionRole::ROLE_USE_RA];
173
            case $role->equals(RegistrationAuthorityRole::raa()):
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
174
                return [InstitutionRole::ROLE_USE_RAA];
175
            default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
176
                return [];
177
        }
178
    }
179
180
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $role should have a doc-comment as per coding-style.
Loading history...
181
     * This is the mapping to look up allowed identity roles for a specific institution role
182
     * - if the required role is RA we should look if the identity has a RA or RAA role
183
     * - if the required role is RAA we should look if the identity has a RAA role
184
     *
185
     */
0 ignored issues
show
Coding Style introduced by
Additional blank lines found at end of doc comment
Loading history...
Coding Style introduced by
Missing @return tag in function comment
Loading history...
186
    private function getAllowedIdentityRoles(RegistrationAuthorityRole $role): array
0 ignored issues
show
Coding Style introduced by
Private method name "AuthorizationRepository::getAllowedIdentityRoles" must be prefixed with an underscore
Loading history...
187
    {
188
        switch (true) {
189
            case $role->equals(RegistrationAuthorityRole::ra()):
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
190
                return [AuthorityRole::ROLE_RA, AuthorityRole::ROLE_RAA];
191
            case $role->equals(RegistrationAuthorityRole::raa()):
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
192
                return [AuthorityRole::ROLE_RAA];
193
            default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
194
                return [];
195
        }
196
    }
197
198
    private function getInstitutionRoleByRaRole(RegistrationAuthorityRole $role): string
0 ignored issues
show
Coding Style introduced by
Private method name "AuthorizationRepository::getInstitutionRoleByRaRole" must be prefixed with an underscore
Loading history...
199
    {
200
        switch (true) {
201
            case $role->equals(RegistrationAuthorityRole::ra()):
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
202
                return AuthorityRole::ROLE_RA;
203
            case $role->equals(RegistrationAuthorityRole::raa()):
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
204
                return AuthorityRole::ROLE_RAA;
205
        }
206
    }
207
}
208