Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 110
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
Lti1p3RegistrationSnapshotRepository
0.00% covered (danger)
0.00%
0 / 110
0.00% covered (danger)
0.00%
0 / 11
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 save
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 1
6
 deleteByStatementId
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 find
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 findAll
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 findByClientId
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 findByPlatformIssuer
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 findByToolIssuer
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRow
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
12
 toRegistration
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
2
 getPersistence
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2022 (original work) Open Assessment Technologies SA;
19 *
20 * @author Ricardo Quintanilha <ricardo.quintanilha@taotesting.com>
21 */
22
23declare(strict_types=1);
24
25namespace oat\taoLti\models\classes\Platform\Repository;
26
27use common_persistence_SqlPersistence as SqlPersistence;
28use oat\generis\persistence\PersistenceManager;
29use OAT\Library\Lti1p3Core\Platform\Platform;
30use OAT\Library\Lti1p3Core\Registration\Registration;
31use OAT\Library\Lti1p3Core\Registration\RegistrationInterface;
32use OAT\Library\Lti1p3Core\Registration\RegistrationRepositoryInterface;
33use OAT\Library\Lti1p3Core\Security\Key\KeyChainRepositoryInterface;
34use oat\taoLti\models\classes\Platform\LtiPlatformRegistration;
35use oat\taoLti\models\classes\Security\DataAccess\Repository\PlatformKeyChainRepository;
36use RuntimeException;
37
38class Lti1p3RegistrationSnapshotRepository implements RegistrationRepositoryInterface
39{
40    /** @var PersistenceManager */
41    private $persistenceManager;
42
43    /** @var KeyChainRepositoryInterface */
44    private $keyChainRepository;
45
46    /** @var PlatformKeyChainRepository */
47    private $platformKeyChainRepository;
48
49    /** @var DefaultToolConfig */
50    private $defaultToolConfig;
51
52    /** @var string */
53    private $persistenceId;
54
55    public function __construct(
56        PersistenceManager $persistenceManager,
57        KeyChainRepositoryInterface $keyChainRepository,
58        PlatformKeyChainRepository $platformKeyChainRepository,
59        DefaultToolConfig $defaultToolConfig,
60        string $persistenceId
61    ) {
62        $this->persistenceManager = $persistenceManager;
63        $this->keyChainRepository = $keyChainRepository;
64        $this->platformKeyChainRepository = $platformKeyChainRepository;
65        $this->defaultToolConfig = $defaultToolConfig;
66        $this->persistenceId = $persistenceId;
67    }
68
69    public function save(LtiPlatformRegistration $ltiPlatformRegistration): void
70    {
71        $registration = $this->find($ltiPlatformRegistration->getIdentifier());
72
73        if ($registration === null) {
74            $this->getPersistence()->insert(
75                'lti_platform_registration',
76                [
77                    'statement_id' => $ltiPlatformRegistration->getIdentifier(),
78                    'name' => $ltiPlatformRegistration->getName(),
79                    'audience' => $ltiPlatformRegistration->getAudience(),
80                    'client_id' => $ltiPlatformRegistration->getClientId(),
81                    'deployment_id' => $ltiPlatformRegistration->getDeploymentId(),
82                    'oidc_authentication_url' => $ltiPlatformRegistration->getOidcAuthenticationUrl(),
83                    'oauth2_access_token_url' => $ltiPlatformRegistration->getOAuth2AccessTokenUrl(),
84                    'jwks_url' => $ltiPlatformRegistration->getJwksUrl(),
85                    'updated_at' => date('Y-m-d H:i:s')
86                ]
87            );
88
89            return;
90        }
91
92        $this->getPersistence()->updateMultiple(
93            'lti_platform_registration',
94            [
95                [
96                    'conditions' => [
97                        'statement_id' => $ltiPlatformRegistration->getIdentifier()
98                    ],
99                    'updateValues' => [
100                        'name' => $ltiPlatformRegistration->getName(),
101                        'audience' => $ltiPlatformRegistration->getAudience(),
102                        'client_id' => $ltiPlatformRegistration->getClientId(),
103                        'deployment_id' => $ltiPlatformRegistration->getDeploymentId(),
104                        'oidc_authentication_url' => $ltiPlatformRegistration->getOidcAuthenticationUrl(),
105                        'oauth2_access_token_url' => $ltiPlatformRegistration->getOAuth2AccessTokenUrl(),
106                        'jwks_url' => $ltiPlatformRegistration->getJwksUrl(),
107                        'updated_at' => date('Y-m-d H:i:s')
108                    ]
109                ]
110            ]
111        );
112    }
113
114    public function deleteByStatementId(string $statementId): void
115    {
116        $this->getPersistence()->exec(
117            'DELETE FROM lti_platform_registration WHERE statement_id = :statement_id',
118            ['statement_id' => $statementId]
119        );
120    }
121
122    public function find(string $identifier): ?RegistrationInterface
123    {
124        $row = $this->getRow(['statement_id' => $identifier]);
125
126        if (empty($row)) {
127            return null;
128        }
129
130        return $this->toRegistration($row);
131    }
132
133    public function findAll(): array
134    {
135        $rows = $this->getPersistence()
136            ->query('SELECT * FROM lti_platform_registration')
137            ->fetchAll();
138
139        return array_map(
140            function (array $row) {
141                return $this->toRegistration($row);
142            },
143            $rows
144        );
145    }
146
147    public function findByClientId(string $clientId): ?RegistrationInterface
148    {
149        $row = $this->getRow(['client_id' => $clientId]);
150
151        if (empty($row)) {
152            return null;
153        }
154
155        return $this->toRegistration($row);
156    }
157
158    public function findByPlatformIssuer(string $issuer, string $clientId = null): ?RegistrationInterface
159    {
160        $queryParams = [
161            'audience' => $issuer,
162            'client_id' => $clientId
163        ];
164
165        $row = $this->getRow($queryParams);
166
167        if (empty($row)) {
168            return null;
169        }
170
171        return $this->toRegistration($row);
172    }
173
174    public function findByToolIssuer(string $issuer, string $clientId = null): ?RegistrationInterface
175    {
176        throw new RuntimeException('Find registration by tool is not supported');
177    }
178
179    private function getRow(array $queryParams = []): array
180    {
181        $queryParams = array_filter($queryParams);
182
183        $query = 'SELECT * FROM lti_platform_registration';
184
185        if (!empty($queryParams)) {
186            $whereClauses = array_map(
187                function ($column) {
188                    return sprintf('%s = :%s', $column, $column);
189                },
190                array_keys($queryParams)
191            );
192
193            $query .= ' WHERE ' . implode(' AND ', $whereClauses);
194        }
195
196        $query .= ' LIMIT 1';
197
198        $statement = $this->getPersistence()->query(
199            $query,
200            $queryParams
201        );
202
203        return $statement->fetch() ?: [];
204    }
205
206    private function toRegistration(array $row): ?Registration
207    {
208        $toolKeyChain = $this->keyChainRepository
209            ->find($this->platformKeyChainRepository->getDefaultKeyId());
210
211        $platform = new Platform(
212            $row['statement_id'],
213            $row['name'],
214            $row['audience'],
215            $row['oidc_authentication_url'],
216            $row['oauth2_access_token_url']
217        );
218
219        return new Registration(
220            $platform->getIdentifier(),
221            $row['client_id'],
222            $platform,
223            $this->defaultToolConfig->getTool(),
224            [$row['deployment_id']],
225            null,
226            $toolKeyChain,
227            $row['jwks_url'],
228            $this->defaultToolConfig->getJwksUrl()
229        );
230    }
231
232    private function getPersistence(): SqlPersistence
233    {
234        return $this->persistenceManager->getPersistenceById($this->persistenceId);
235    }
236}