generationIsActive()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace rhertogh\Yii2Oauth2Server\migrations;
4
5
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2AccessTokenInterface;
6
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2AccessTokenScopeInterface;
7
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2AuthCodeInterface;
8
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2AuthCodeScopeInterface;
9
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ClientInterface;
10
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ClientScopeInterface;
11
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2RefreshTokenInterface;
12
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2ScopeInterface;
13
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2UserClientInterface;
14
use rhertogh\Yii2Oauth2Server\interfaces\models\Oauth2UserClientScopeInterface;
15
use rhertogh\Yii2Oauth2Server\migrations\base\Oauth2BaseMigration;
16
use rhertogh\Yii2Oauth2Server\models\Oauth2AccessToken;
17
use rhertogh\Yii2Oauth2Server\Oauth2Module;
18
use yii\base\InvalidConfigException;
19
use yii\db\ColumnSchemaBuilder;
20
21
/**
22
 * phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
23
 * phpcs:disable Generic.Files.LineLength.TooLong
24
 */
25
abstract class Oauth2_00001_CreateOauth2TablesMigration extends Oauth2BaseMigration
26
{
27
    /**
28
     * @var int Number of tables expected to be returned by getTables(),
29
     * when dependency injection is misconfigured this can be off.
30
     */
31
    protected $numTables = 10;
32
33
    /**
34
     * @inheritDoc
35
     */
36 1
    public static function generationIsActive($module)
37
    {
38 1
        return true;
39
    }
40
41
    /**
42
     * @inheritDoc
43
     */
44 2
    public function safeUp()
45
    {
46 2
        foreach ($this->getTables() as $table => $definition) {
47
48 2
            $tableDefinition = $definition['table'];
49 2
            if (!$this->commentsSupported()) {
50
                foreach ($tableDefinition as $tableColumn) { /** @var ColumnSchemaBuilder $tableColumn */
51
                    $tableColumn->comment(null);
52
                }
53
            }
54 2
            if (!empty($definition['primaryKey']) && !$this->deferredPrimaryKeyCreationSupported()) {
55
                $tableDefinition[] = 'PRIMARY KEY (' . implode(', ', $definition['primaryKey']['columns']) . ')';
56
            }
57 2
            if (!empty($definition['foreignKeys']) && !$this->deferredForeignKeyCreationSupported()) {
58
                foreach ($definition['foreignKeys'] as $foreignKey) {
59
                    $tableDefinition[] = 'FOREIGN KEY (' . implode(', ', $foreignKey['columns']) . ')'
60
                        . ' REFERENCES ' . $foreignKey['refTable'] . '(' . implode(', ', $foreignKey['refColumns']) . ')'
61
                        . ' ON DELETE ' . $foreignKey['delete'] . ' ON UPDATE ' . $foreignKey['update'];
62
                }
63
            }
64
65 2
            $this->createTable($table, $tableDefinition);
66 2
            $rawTableName = $this->getDb()->getSchema()->getRawTableName($table);
67
68 2
            if (!empty($definition['primaryKey']) && $this->deferredPrimaryKeyCreationSupported()) {
69 2
                $this->addPrimaryKey(
70 2
                    $rawTableName . '_pk',
71 2
                    $table,
72 2
                    $definition['primaryKey']['columns']
73 2
                );
74
            }
75
76 2
            if (!empty($definition['indexes'])) {
77 2
                foreach ($definition['indexes'] as $index) {
78 2
                    $this->createIndex(
79 2
                        $rawTableName . '_' . $index['name'] . '_index',
80 2
                        $table,
81 2
                        $index['columns'],
82 2
                        $index['unique']
83 2
                    );
84
                }
85
            }
86
87 2
            if (!empty($definition['foreignKeys']) && $this->deferredForeignKeyCreationSupported()) {
88 2
                foreach ($definition['foreignKeys'] as $foreignKey) {
89 2
                    $this->addForeignKey(
90 2
                        $rawTableName . '_' . $foreignKey['name'] . '_fk',
91 2
                        $table,
92 2
                        $foreignKey['columns'],
93 2
                        $foreignKey['refTable'],
94 2
                        $foreignKey['refColumns'],
95 2
                        $foreignKey['delete'],
96 2
                        $foreignKey['update'],
97 2
                    );
98
                }
99
            }
100
        }
101
    }
102
103
    /**
104
     * @inheritDoc
105
     */
106 2
    public function safeDown()
107
    {
108 2
        foreach (array_reverse($this->getTables()) as $table => $definition) {
109 2
            $this->dropTable($table);
110
        }
111
    }
112
113
    /**
114
     * Get all table definitions.
115
     * @return array[]
116
     * @throws InvalidConfigException
117
     * @since 1.0.0
118
     */
119 5
    protected function getTables()
120
    {
121 5
        $module = Oauth2Module::getInstance();
122 5
        if (empty($module)) {
123 1
            throw new InvalidConfigException('Oauth2Module is not instantiated. Is it added to the config in the "module" and "bootstrap" section?');
124
        }
125
126 4
        $accessTokenTable = $this->getTableName(Oauth2AccessTokenInterface::class);
127 4
        $accessTokenScopeTable = $this->getTableName(Oauth2AccessTokenScopeInterface::class);
128 4
        $authCodeTable = $this->getTableName(Oauth2AuthCodeInterface::class);
129 4
        $authCodeScopeTable = $this->getTableName(Oauth2AuthCodeScopeInterface::class);
130 4
        $clientTable = $this->getTableName(Oauth2ClientInterface::class);
131 4
        $clientScopeTable = $this->getTableName(Oauth2ClientScopeInterface::class);
132 4
        $refreshTokenTable = $this->getTableName(Oauth2RefreshTokenInterface::class);
133 4
        $scopeTable = $this->getTableName(Oauth2ScopeInterface::class);
134 4
        $userClientTable = $this->getTableName(Oauth2UserClientInterface::class);
135 4
        $userClientScopeTable = $this->getTableName(Oauth2UserClientScopeInterface::class);
136
137 4
        $userTableSchema = $this->getTableSchema($module->identityClass);
138 4
        if ($userTableSchema) {
0 ignored issues
show
introduced by
$userTableSchema is of type yii\db\TableSchema, thus it always evaluated to true.
Loading history...
139 3
            if (count($userTableSchema->primaryKey) != 1) {
140 1
                throw new InvalidConfigException('The primary key of `userClass` must consist of a single column');
141
            }
142 2
            $userTable = $userTableSchema->name;
143 2
            $userPkColumn = $userTableSchema->primaryKey[0];
144 2
            $userPkSchema = $userTableSchema->columns[$userPkColumn];
145
        } else {
146 1
            $userTable = false;
147 1
            $userPkColumn = null;
148 1
            $userPkSchema = null;
149
        }
150
151 3
        if ($userPkSchema) {
0 ignored issues
show
introduced by
$userPkSchema is of type yii\db\ColumnSchema, thus it always evaluated to true.
Loading history...
152 2
            $userPkSchemaColumnBuilder = $this->getColumnSchemaBuilder($userPkSchema);
153
        } else {
154 1
            $userPkSchemaColumnBuilder = $this->string();
155
        }
156
157
        // See https://datatracker.ietf.org/doc/html/rfc7591#section-2
158
        // (although not yet fully implemented, some fields follow this standard).
159 3
        $tables = [
160 3
            $clientTable => [
161 3
                'table' => [
162 3
                    'id' => $this->primaryKey(),
163 3
                    'identifier' => $this->string()->notNull()->unique()
164 3
                        ->comment('Unique textual identifier by which the Client identifies itself.'),
165 3
                    'name' => $this->string()->notNull()
166 3
                        ->comment('Descriptive name of the Client'),
167 3
                    'type' => $this->integer()->notNull()->defaultValue(Oauth2ClientInterface::TYPE_CONFIDENTIAL)
168 3
                        ->comment('Client type, "confidential" clients must authenticate themselves via a "client secret".'),
169 3
                    'secret' => $this->text()
170 3
                        ->comment('"Confidential" clients must authenticate themselves via this secret.'),
171 3
                    'old_secret' => $this->text()
172 3
                        ->comment('Checked when the `secret` does not match, can be used for key rotation.'),
173 3
                    'old_secret_valid_until' => $this->dateTime()
174 3
                        ->comment('Determines till which date the `old_secret` may be used.'),
175 3
                    'env_var_config' => $this->json()
176 3
                        ->comment('Configuration for environment variable replacement in the `redirect_uris`, setting this value overrides the `Oauth2Module::$clientRedirectUrisEnvVarConfig`.'),
177 3
                    'logo_uri' => $this->string()
178 3
                        ->comment('Logo which is presented to the end user during client authorization.'),
179 3
                    'tos_uri' => $this->string()
180 3
                        ->comment('Link to the "Term of Service" which is presented to the end user during client authorization.'),
181 3
                    'contacts' => $this->json()
182 3
                        ->comment('Array of e-mail addresses of people responsible for this Client.'),
183 3
                    'redirect_uris' => $this->json()
184 3
                        ->comment('Array of redirect uris which the Client is allowed to use.'),
185 3
                    'post_logout_redirect_uris' => $this->json()
186 3
                        ->comment('Array of post logout redirect uris which the Client is allowed to use.'),
187 3
                    'allow_variable_redirect_uri_query' => $this->boolean()->notNull()->defaultValue(false)
188 3
                        ->comment('By default, the client is validated against the full redirect URI including the "query" part. If the "query" part of the return URI is variable it may be marked as such.'),
189 3
                    'token_types' => $this->integer()->notNull()->defaultValue(Oauth2AccessToken::TYPE_BEARER),
190 3
                    'grant_types' => $this->integer()->notNull()->defaultValue(Oauth2Module::GRANT_TYPE_AUTH_CODE | Oauth2Module::GRANT_TYPE_REFRESH_TOKEN)
191 3
                        ->comment('Oauth2 grant types enabled for this Client.'),
192 3
                    'allow_generic_scopes' => $this->boolean()->notNull()->defaultValue(false)
193 3
                        ->comment('Determines if scopes must be explicitly linked this client (default) or all defined scopes may be used.'),
194 3
                    'exception_on_invalid_scope' => $this->boolean()
195 3
                        ->comment('Determines if an exception is thrown when the Client requests an unknown scope.'),
196 3
                    'end_users_may_authorize_client' => $this->boolean()->notNull()->defaultValue(true)
197 3
                        ->comment('Determines if the user can authorize a client (the client has to be pre-authorized otherwise).'),
198 3
                    'user_account_selection' => $this->integer()
199 3
                        ->comment('Determines when to show user account selection screen. Using Oauth2Module::$defaultUserAccountSelection when `null`.'),
200 3
                    'allow_auth_code_without_pkce' => $this->boolean()->notNull()->defaultValue(false)
201 3
                        ->comment('Require clients to use PKCE when using the auth_code grant type.'),
202 3
                    'skip_authorization_if_scope_is_allowed' => $this->boolean()->notNull()->defaultValue(false)
203 3
                        ->comment('Skip user authorization of client if there are no scopes that require authorization.'),
204 3
                    'client_credentials_grant_user_id' => (clone $userPkSchemaColumnBuilder)
205 3
                        ->comment("Optional user id to use in case of grant type 'client_credentials'."
206 3
                        . " This user account should also be connected to the client via the `$userClientTable` table and, if applicable, the `$userClientScopeTable` table."),
207 3
                    'oidc_allow_offline_access_without_consent' => $this->boolean()->notNull()->defaultValue(false)
208 3
                        ->comment('Allow the OpenID Connect "offline_access" scope for this client without the "prompt" parameter contains "consent".'),
209 3
                    'oidc_rp_initiated_logout' => $this->integer()->notNull()->defaultValue(Oauth2ClientInterface::OIDC_RP_INITIATED_LOGOUT_DISABLED)
210 3
                        ->comment('Configuration for OpenID Connect RP-Initiated Logout.'),
211 3
                    'oidc_userinfo_encrypted_response_alg' => $this->string(),
212 3
                    'enabled' => $this->boolean()->notNull()->defaultValue(true),
213 3
                    'created_at' => $this->integer()->notNull(),
214 3
                    'updated_at' => $this->integer()->notNull(),
215 3
                ],
216 3
                'foreignKeys' => [
217 3
                    ...(
218 3
                        $userTable
219 2
                        ? [
220 2
                            [
221 2
                                'name' => 'client_credentials_grant_user_id',
222 2
                                'columns' => ['client_credentials_grant_user_id'],
223 2
                                'refTable' => $userTable,
224 2
                                'refColumns' => [$userPkColumn],
225 2
                                'delete' => static::RESTRICT,
226 2
                                'update' => static::CASCADE,
227 2
                            ],
228 2
                        ]
229
                        : []
230 3
                    ),
231 3
                ],
232 3
                'indexes' => [
233 3
                    ...(
234 3
                        !$userTable
235
                        ? [
236
                            [
237
                                'name' => 'client_credentials_grant_user_id',
238
                                'columns' => ['client_credentials_grant_user_id'],
239
                                'unique' => false,
240
                            ],
241
                        ]
242
                        : []
243 3
                    ),
244 3
                    [
245 3
                        'name' => 'token_types',
246 3
                        'columns' => ['token_types'],
247 3
                        'unique' => false,
248 3
                    ],
249 3
                    [
250 3
                        'name' => 'grant_types',
251 3
                        'columns' => ['grant_types'],
252 3
                        'unique' => false,
253 3
                    ],
254 3
                    [
255 3
                        'name' => 'enabled',
256 3
                        'columns' => ['enabled'],
257 3
                        'unique' => false,
258 3
                    ],
259 3
                ],
260 3
            ],
261
262 3
            $scopeTable => [
263 3
                'table' => [
264 3
                    'id' => $this->primaryKey(),
265 3
                    'identifier' => $this->string()->notNull()->unique()
266 3
                        ->comment('Unique textual identifier by which the Client identifies the scope.'),
267 3
                    'description' => $this->text()
268 3
                        ->comment('Descriptive text about this scope.'),
269 3
                    'authorization_message' => $this->text()
270 3
                        ->comment('Message that is shown to the end user on the Client authorization screen for this scope.'),
271 3
                    'applied_by_default' => $this->integer()->notNull()->defaultValue(Oauth2ScopeInterface::APPLIED_BY_DEFAULT_NO)
272 3
                        ->comment('Should this scope be applied without the Client specifically requesting it, and if so, does the end user needs to authorize it.'),
273 3
                    'required_on_authorization' => $this->boolean()->notNull()->defaultValue(true)
274 3
                        ->comment('Is this scope required or optional on the Client authorization screen.'),
275 3
                    'enabled' => $this->boolean()->notNull()->defaultValue(true),
276 3
                    'created_at' => $this->integer()->notNull(),
277 3
                    'updated_at' => $this->integer()->notNull(),
278 3
                ],
279 3
                'indexes' => [
280 3
                    [
281 3
                        'name' => 'applied_by_default',
282 3
                        'columns' => ['applied_by_default'],
283 3
                        'unique' => false,
284 3
                    ],
285 3
                    [
286 3
                        'name' => 'enabled',
287 3
                        'columns' => ['enabled'],
288 3
                        'unique' => false,
289 3
                    ],
290 3
                ],
291 3
            ],
292
293 3
            $clientScopeTable => [
294 3
                'table' => [
295 3
                    'client_id' => $this->integer()->notNull(),
296 3
                    'scope_id' => $this->integer()->notNull(),
297 3
                    'applied_by_default' => $this->integer()
298 3
                        ->comment('Should this scope be applied without the Client specifically requesting it, and if so, does the end user needs to authorize it. Note: Setting this value overrides the `scope.applied_by_default`.'),
299 3
                    'required_on_authorization' => $this->boolean()
300 3
                        ->comment('Is this scope required or optional on the Client authorization screen. Note: Setting this value overrides the `scope.required_on_authorization`.'),
301 3
                    'enabled' => $this->boolean()->notNull()->defaultValue(true),
302 3
                    'created_at' => $this->integer()->notNull(),
303 3
                    'updated_at' => $this->integer()->notNull(),
304 3
                ],
305 3
                'primaryKey' => [
306 3
                    'columns' => ['client_id', 'scope_id'],
307 3
                ],
308 3
                'foreignKeys' => [
309 3
                    [
310 3
                        'name' => 'client_id',
311 3
                        'columns' => ['client_id'],
312 3
                        'refTable' => $clientTable,
313 3
                        'refColumns' => ['id'],
314 3
                        'delete' => static::CASCADE,
315 3
                        'update' => static::CASCADE,
316 3
                    ],
317 3
                    [
318 3
                        'name' => 'scope_id',
319 3
                        'columns' => ['scope_id'],
320 3
                        'refTable' => $scopeTable,
321 3
                        'refColumns' => ['id'],
322 3
                        'delete' => static::CASCADE,
323 3
                        'update' => static::CASCADE,
324 3
                    ],
325 3
                ],
326 3
                'indexes' => [
327 3
                    [
328 3
                        'name' => 'applied_by_default',
329 3
                        'columns' => ['applied_by_default'],
330 3
                        'unique' => false,
331 3
                    ],
332 3
                    [
333 3
                        'name' => 'enabled',
334 3
                        'columns' => ['enabled'],
335 3
                        'unique' => false,
336 3
                    ],
337 3
                ],
338 3
            ],
339
340 3
            $authCodeTable => [
341 3
                'table' => [
342 3
                    'id' => $this->bigPrimaryKey()->unsigned(),
343 3
                    'identifier' => $this->string()->notNull()->unique(),
344 3
                    'redirect_uri' => $this->string(),
345 3
                    'expiry_date_time' => $this->dateTime()->notNull(),
346 3
                    'client_id' => $this->integer()->notNull(),
347 3
                    'user_id' => (clone $userPkSchemaColumnBuilder)->notNull(),
348 3
                    'enabled' => $this->boolean()->notNull()->defaultValue(true), // ToDo: do we need this ???
349 3
                    'created_at' => $this->integer()->notNull(),
350 3
                    'updated_at' => $this->integer()->notNull(),
351 3
                ],
352 3
                'foreignKeys' => [
353 3
                    [
354 3
                        'name' => 'client_id',
355 3
                        'columns' => ['client_id'],
356 3
                        'refTable' => $clientTable,
357 3
                        'refColumns' => ['id'],
358 3
                        'delete' => static::CASCADE,
359 3
                        'update' => static::CASCADE,
360 3
                    ],
361 3
                    ...(
362 3
                        $userTable
363 2
                        ? [
364 2
                            [
365 2
                                'name' => 'user_id',
366 2
                                'columns' => ['user_id'],
367 2
                                'refTable' => $userTable,
368 2
                                'refColumns' => [$userPkColumn],
369 2
                                'delete' => static::CASCADE,
370 2
                                'update' => static::CASCADE,
371 2
                            ],
372 2
                        ]
373
                        : []
374 3
                    ),
375 3
                ],
376 3
                'indexes' => [
377 3
                    ...(
378 3
                        !$userTable
379
                        ? [
380
                            [
381
                                'name' => 'user_id',
382
                                'columns' => ['user_id'],
383
                                'unique' => false,
384
                            ],
385
                        ]
386
                        : []
387 3
                    ),
388 3
                    [
389 3
                        'name' => 'enabled',
390 3
                        'columns' => ['enabled'],
391 3
                        'unique' => false,
392 3
                    ],
393 3
                ],
394 3
            ],
395
396 3
            $authCodeScopeTable => [
397 3
                'table' => [
398 3
                    'auth_code_id' => $this->bigInteger()->unsigned()->notNull(),
399 3
                    'scope_id' => $this->integer()->notNull(),
400 3
                    'created_at' => $this->integer()->notNull(),
401 3
                ],
402 3
                'primaryKey' => [
403 3
                    'columns' => ['auth_code_id', 'scope_id'],
404 3
                ],
405 3
                'foreignKeys' => [
406 3
                    [
407 3
                        'name' => 'auth_code_id',
408 3
                        'columns' => ['auth_code_id'],
409 3
                        'refTable' => $authCodeTable,
410 3
                        'refColumns' => ['id'],
411 3
                        'delete' => static::CASCADE,
412 3
                        'update' => static::CASCADE,
413 3
                    ],
414 3
                    [
415 3
                        'name' => 'scope_id',
416 3
                        'columns' => ['scope_id'],
417 3
                        'refTable' => $scopeTable,
418 3
                        'refColumns' => ['id'],
419 3
                        'delete' => static::CASCADE,
420 3
                        'update' => static::CASCADE,
421 3
                    ],
422 3
                ],
423 3
            ],
424
425 3
            $accessTokenTable => [
426 3
                'table' => [
427 3
                    'id' => $this->bigPrimaryKey()->unsigned(),
428 3
                    'identifier' => $this->string()->notNull()->unique(),
429 3
                    'client_id' => $this->integer()->notNull(),
430 3
                    'user_id' => (clone $userPkSchemaColumnBuilder),
431 3
                    'type' => $this->integer()->notNull(),
432 3
                    'mac_key' => $this->string(500),
433 3
                    'mac_algorithm' => $this->smallInteger(),
434 3
                    'allowance' => $this->smallInteger(),
435 3
                    'allowance_updated_at' => $this->integer(),
436 3
                    'expiry_date_time' => $this->dateTime()->notNull(),
437 3
                    'enabled' => $this->boolean()->notNull()->defaultValue(true),
438 3
                    'created_at' => $this->integer()->notNull(),
439 3
                    'updated_at' => $this->integer()->notNull(),
440 3
                ],
441 3
                'foreignKeys' => [
442 3
                    [
443 3
                        'name' => 'client_id',
444 3
                        'columns' => ['client_id'],
445 3
                        'refTable' => $clientTable,
446 3
                        'refColumns' => ['id'],
447 3
                        'delete' => static::CASCADE,
448 3
                        'update' => static::CASCADE,
449 3
                    ],
450 3
                    ...(
451 3
                        $userTable
452 2
                        ? [
453 2
                            [
454 2
                                'name' => 'user_id',
455 2
                                'columns' => ['user_id'],
456 2
                                'refTable' => $userTable,
457 2
                                'refColumns' => [$userPkColumn],
458 2
                                'delete' => static::CASCADE,
459 2
                                'update' => static::CASCADE,
460 2
                            ],
461 2
                        ]
462
                        : []
463 3
                    ),
464 3
                ],
465 3
                'indexes' => [
466 3
                    ...(
467 3
                        !$userTable
468
                        ? [
469
                            [
470
                                'name' => 'user_id',
471
                                'columns' => ['user_id'],
472
                                'unique' => false,
473
                            ],
474
                        ]
475
                        : []
476 3
                    ),
477 3
                    [
478 3
                        'name' => 'type',
479 3
                        'columns' => ['type'],
480 3
                        'unique' => false,
481 3
                    ],
482 3
                    [
483 3
                        'name' => 'mac_algorithm',
484 3
                        'columns' => ['mac_algorithm'],
485 3
                        'unique' => false,
486 3
                    ],
487 3
                    [
488 3
                        'name' => 'enabled',
489 3
                        'columns' => ['enabled'],
490 3
                        'unique' => false,
491 3
                    ],
492 3
                ],
493 3
            ],
494
495 3
            $accessTokenScopeTable => [
496 3
                'table' => [
497 3
                    'access_token_id' => $this->bigInteger()->unsigned()->notNull(),
498 3
                    'scope_id' => $this->integer()->notNull(),
499 3
                    'created_at' => $this->integer()->notNull(),
500 3
                ],
501 3
                'primaryKey' => [
502 3
                    'columns' => ['access_token_id', 'scope_id'],
503 3
                ],
504 3
                'foreignKeys' => [
505 3
                    [
506 3
                        'name' => 'access_token_id',
507 3
                        'columns' => ['access_token_id'],
508 3
                        'refTable' => $accessTokenTable,
509 3
                        'refColumns' => ['id'],
510 3
                        'delete' => static::CASCADE,
511 3
                        'update' => static::CASCADE,
512 3
                    ],
513 3
                    [
514 3
                        'name' => 'scope_id',
515 3
                        'columns' => ['scope_id'],
516 3
                        'refTable' => $scopeTable,
517 3
                        'refColumns' => ['id'],
518 3
                        'delete' => static::CASCADE,
519 3
                        'update' => static::CASCADE,
520 3
                    ],
521 3
                ],
522 3
            ],
523
524 3
            $refreshTokenTable => [
525 3
                'table' => [
526 3
                    'id' => $this->bigPrimaryKey()->unsigned(),
527 3
                    'access_token_id' => $this->bigInteger()->unsigned(),
528 3
                    'identifier' => $this->string()->notNull()->unique(),
529 3
                    'expiry_date_time' => $this->dateTime()->notNull(),
530 3
                    'enabled' => $this->boolean()->notNull()->defaultValue(true),
531 3
                    'created_at' => $this->integer()->notNull(),
532 3
                    'updated_at' => $this->integer()->notNull(),
533 3
                ],
534 3
                'foreignKeys' => [
535 3
                    [
536 3
                        'name' => 'access_token_id',
537 3
                        'columns' => ['access_token_id'],
538 3
                        'refTable' => $accessTokenTable,
539 3
                        'refColumns' => ['id'],
540 3
                        'delete' => static::CASCADE,
541 3
                        'update' => static::CASCADE,
542 3
                    ],
543 3
                ],
544 3
                'indexes' => [
545 3
                    [
546 3
                        'name' => 'enabled',
547 3
                        'columns' => ['enabled'],
548 3
                        'unique' => false,
549 3
                    ],
550 3
                ],
551 3
            ],
552
553 3
            $userClientTable => [
554 3
                'table' => [
555 3
                    'user_id' => (clone $userPkSchemaColumnBuilder)->notNull(),
556 3
                    'client_id' => $this->integer()->notNull(),
557 3
                    'enabled' => $this->boolean()->notNull()->defaultValue(true),
558 3
                    'created_at' => $this->integer()->notNull(),
559 3
                    'updated_at' => $this->integer()->notNull(),
560 3
                ],
561 3
                'primaryKey' => [
562 3
                    'columns' => ['user_id', 'client_id'],
563 3
                ],
564 3
                'foreignKeys' => [
565 3
                    [
566 3
                        'name' => 'client_id',
567 3
                        'columns' => ['client_id'],
568 3
                        'refTable' => $clientTable,
569 3
                        'refColumns' => ['id'],
570 3
                        'delete' => static::CASCADE,
571 3
                        'update' => static::CASCADE,
572 3
                    ],
573 3
                    ...(
574 3
                        $userTable
575 2
                        ? [
576 2
                            [
577 2
                                'name' => 'user_id',
578 2
                                'columns' => ['user_id'],
579 2
                                'refTable' => $userTable,
580 2
                                'refColumns' => [$userPkColumn],
581 2
                                'delete' => static::CASCADE,
582 2
                                'update' => static::CASCADE,
583 2
                            ],
584 2
                        ]
585
                        : []
586 3
                    ),
587 3
                ],
588 3
                'indexes' => [
589 3
                    ...(
590 3
                        !$userTable
591
                        ? [
592
                            [
593
                                'name' => 'user_id',
594
                                'columns' => ['user_id'],
595
                                'unique' => false,
596
                            ],
597
                        ]
598
                        : []
599 3
                    ),
600 3
                    [
601 3
                        'name' => 'enabled',
602 3
                        'columns' => ['enabled'],
603 3
                        'unique' => false,
604 3
                    ],
605 3
                ],
606 3
            ],
607
608 3
            $userClientScopeTable => [
609 3
                'table' => [
610 3
                    'user_id' => (clone $userPkSchemaColumnBuilder)->notNull(),
611 3
                    'client_id' => $this->integer()->notNull(),
612 3
                    'scope_id' => $this->integer()->notNull(),
613 3
                    'enabled' => $this->boolean()->notNull()->defaultValue(true),
614 3
                    'created_at' => $this->integer()->notNull(),
615 3
                    'updated_at' => $this->integer()->notNull(),
616 3
                ],
617 3
                'primaryKey' => [
618 3
                    'columns' => ['user_id', 'client_id', 'scope_id'],
619 3
                ],
620 3
                'foreignKeys' => [
621 3
                    [
622 3
                        'name' => 'user_client_id',
623 3
                        'columns' => ['user_id', 'client_id'],
624 3
                        'refTable' => $userClientTable,
625 3
                        'refColumns' => ['user_id', 'client_id'],
626 3
                        'delete' => static::CASCADE,
627 3
                        'update' => static::CASCADE,
628 3
                    ],
629 3
                    [ # Note: Not connected to client_scope table since scopes can also be applied by default to all clients
630 3
                        'name' => 'scope_id',
631 3
                        'columns' => ['scope_id'],
632 3
                        'refTable' => $scopeTable,
633 3
                        'refColumns' => ['id'],
634 3
                        'delete' => static::CASCADE,
635 3
                        'update' => static::CASCADE,
636 3
                    ],
637 3
                ],
638 3
                'indexes' => [
639 3
                    [
640 3
                        'name' => 'enabled',
641 3
                        'columns' => ['enabled'],
642 3
                        'unique' => false,
643 3
                    ],
644 3
                ],
645 3
            ],
646 3
        ];
647
648 3
        if (count(array_unique(array_keys($tables))) != $this->numTables) {
649 1
            throw new InvalidConfigException('Incorrect number of tables in definition. Are the Active Record classes correctly configured?');
650
        }
651
652 2
        return $tables;
653
    }
654
655
//    /**
656
//     * @param string $tableClass
657
//     * @return ActiveRecord
658
//     * @throws InvalidConfigException
659
//     */
660
//    protected function getArInstance($tableClass)
661
//    {
662
//        $activeRecord = Yii::createObject($tableClass);
663
//
664
//        if (!($activeRecord instanceof ActiveRecord)) {
665
//            throw new InvalidConfigException($tableClass . ' must be an instance of ActiveRecord');
666
//        }
667
//
668
//        return $activeRecord;
669
//    }
670
}
671