mirror of
				https://github.com/elyby/accounts.git
				synced 2025-05-31 14:11:46 +05:30 
			
		
		
		
	Implemented features to revoke access for previously authorized OAuth 2.0 clients
This commit is contained in:
		@@ -8,6 +8,8 @@ return [
 | 
			
		||||
    'DELETE /v1/oauth2/<clientId>' => 'oauth/clients/delete',
 | 
			
		||||
    'POST /v1/oauth2/<clientId>/reset' => 'oauth/clients/reset',
 | 
			
		||||
    'GET /v1/accounts/<accountId:\d+>/oauth2/clients' => 'oauth/clients/get-per-account',
 | 
			
		||||
    'GET /v1/accounts/<accountId:\d+>/oauth2/authorized' => 'oauth/clients/get-authorized-clients',
 | 
			
		||||
    'DELETE /v1/accounts/<accountId:\d+>/oauth2/authorized/<clientId>' => 'oauth/clients/revoke-client',
 | 
			
		||||
    '/account/v1/info' => 'oauth/identity/index',
 | 
			
		||||
 | 
			
		||||
    // Accounts module routes
 | 
			
		||||
 
 | 
			
		||||
@@ -87,17 +87,19 @@ class AuthenticationForm extends ApiForm {
 | 
			
		||||
        $token = Yii::$app->tokensFactory->createForMinecraftAccount($account, $this->clientToken);
 | 
			
		||||
        $dataModel = new AuthenticateData($account, (string)$token, $this->clientToken);
 | 
			
		||||
        /** @var OauthSession|null $minecraftOauthSession */
 | 
			
		||||
        $hasMinecraftOauthSession = $account->getOauthSessions()
 | 
			
		||||
        $minecraftOauthSession = $account->getOauthSessions()
 | 
			
		||||
            ->andWhere(['client_id' => OauthClient::UNAUTHORIZED_MINECRAFT_GAME_LAUNCHER])
 | 
			
		||||
            ->exists();
 | 
			
		||||
        if ($hasMinecraftOauthSession === false) {
 | 
			
		||||
            ->one();
 | 
			
		||||
        if ($minecraftOauthSession === null) {
 | 
			
		||||
            $minecraftOauthSession = new OauthSession();
 | 
			
		||||
            $minecraftOauthSession->account_id = $account->id;
 | 
			
		||||
            $minecraftOauthSession->client_id = OauthClient::UNAUTHORIZED_MINECRAFT_GAME_LAUNCHER;
 | 
			
		||||
            $minecraftOauthSession->scopes = [P::MINECRAFT_SERVER_SESSION];
 | 
			
		||||
            Assert::true($minecraftOauthSession->save());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $minecraftOauthSession->last_used_at = time();
 | 
			
		||||
        Assert::true($minecraftOauthSession->save());
 | 
			
		||||
 | 
			
		||||
        Authserver::info("User with id = {$account->id}, username = '{$account->username}' and email = '{$account->email}' successfully logged in.");
 | 
			
		||||
 | 
			
		||||
        return $dataModel;
 | 
			
		||||
 
 | 
			
		||||
@@ -70,17 +70,19 @@ class RefreshTokenForm extends ApiForm {
 | 
			
		||||
 | 
			
		||||
        // TODO: This behavior duplicates with the AuthenticationForm. Need to find a way to avoid duplication.
 | 
			
		||||
        /** @var OauthSession|null $minecraftOauthSession */
 | 
			
		||||
        $hasMinecraftOauthSession = $account->getOauthSessions()
 | 
			
		||||
        $minecraftOauthSession = $account->getOauthSessions()
 | 
			
		||||
            ->andWhere(['client_id' => OauthClient::UNAUTHORIZED_MINECRAFT_GAME_LAUNCHER])
 | 
			
		||||
            ->exists();
 | 
			
		||||
        if ($hasMinecraftOauthSession === false) {
 | 
			
		||||
            ->one();
 | 
			
		||||
        if ($minecraftOauthSession === null) {
 | 
			
		||||
            $minecraftOauthSession = new OauthSession();
 | 
			
		||||
            $minecraftOauthSession->account_id = $account->id;
 | 
			
		||||
            $minecraftOauthSession->client_id = OauthClient::UNAUTHORIZED_MINECRAFT_GAME_LAUNCHER;
 | 
			
		||||
            $minecraftOauthSession->scopes = [P::MINECRAFT_SERVER_SESSION];
 | 
			
		||||
            Assert::true($minecraftOauthSession->save());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $minecraftOauthSession->last_used_at = time();
 | 
			
		||||
        Assert::true($minecraftOauthSession->save());
 | 
			
		||||
 | 
			
		||||
        return new AuthenticateData($account, (string)$token, $this->clientToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
<?php
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace api\modules\oauth\controllers;
 | 
			
		||||
 | 
			
		||||
use api\controllers\Controller;
 | 
			
		||||
@@ -11,7 +13,10 @@ use common\models\Account;
 | 
			
		||||
use common\models\OauthClient;
 | 
			
		||||
use Webmozart\Assert\Assert;
 | 
			
		||||
use Yii;
 | 
			
		||||
use yii\db\ActiveQuery;
 | 
			
		||||
use yii\db\Expression;
 | 
			
		||||
use yii\filters\AccessControl;
 | 
			
		||||
use yii\filters\VerbFilter;
 | 
			
		||||
use yii\helpers\ArrayHelper;
 | 
			
		||||
use yii\web\NotFoundHttpException;
 | 
			
		||||
 | 
			
		||||
@@ -31,32 +36,47 @@ class ClientsController extends Controller {
 | 
			
		||||
                        'actions' => ['update', 'delete', 'reset'],
 | 
			
		||||
                        'allow' => true,
 | 
			
		||||
                        'permissions' => [P::MANAGE_OAUTH_CLIENTS],
 | 
			
		||||
                        'roleParams' => function() {
 | 
			
		||||
                            return [
 | 
			
		||||
                                'clientId' => Yii::$app->request->get('clientId'),
 | 
			
		||||
                            ];
 | 
			
		||||
                        },
 | 
			
		||||
                        'roleParams' => fn() => [
 | 
			
		||||
                            'clientId' => Yii::$app->request->get('clientId'),
 | 
			
		||||
                        ],
 | 
			
		||||
                    ],
 | 
			
		||||
                    [
 | 
			
		||||
                        'actions' => ['get'],
 | 
			
		||||
                        'allow' => true,
 | 
			
		||||
                        'permissions' => [P::VIEW_OAUTH_CLIENTS],
 | 
			
		||||
                        'roleParams' => function() {
 | 
			
		||||
                            return [
 | 
			
		||||
                                'clientId' => Yii::$app->request->get('clientId'),
 | 
			
		||||
                            ];
 | 
			
		||||
                        },
 | 
			
		||||
                        'roleParams' => fn() => [
 | 
			
		||||
                            'clientId' => Yii::$app->request->get('clientId'),
 | 
			
		||||
                        ],
 | 
			
		||||
                    ],
 | 
			
		||||
                    [
 | 
			
		||||
                        'actions' => ['get-per-account'],
 | 
			
		||||
                        'allow' => true,
 | 
			
		||||
                        'permissions' => [P::VIEW_OAUTH_CLIENTS],
 | 
			
		||||
                        'roleParams' => function() {
 | 
			
		||||
                            return [
 | 
			
		||||
                                'accountId' => Yii::$app->request->get('accountId'),
 | 
			
		||||
                            ];
 | 
			
		||||
                        },
 | 
			
		||||
                        'roleParams' => fn() => [
 | 
			
		||||
                            'accountId' => Yii::$app->request->get('accountId'),
 | 
			
		||||
                        ],
 | 
			
		||||
                    ],
 | 
			
		||||
                    [
 | 
			
		||||
                        'actions' => ['get-authorized-clients', 'revoke-client'],
 | 
			
		||||
                        'allow' => true,
 | 
			
		||||
                        'permissions' => [P::MANAGE_OAUTH_SESSIONS],
 | 
			
		||||
                        'roleParams' => fn() => [
 | 
			
		||||
                            'accountId' => Yii::$app->request->get('accountId'),
 | 
			
		||||
                        ],
 | 
			
		||||
                    ],
 | 
			
		||||
                ],
 | 
			
		||||
            ],
 | 
			
		||||
            'verb' => [
 | 
			
		||||
                'class' => VerbFilter::class,
 | 
			
		||||
                'actions' => [
 | 
			
		||||
                    'get' => ['GET'],
 | 
			
		||||
                    'create' => ['POST'],
 | 
			
		||||
                    'update' => ['PUT'],
 | 
			
		||||
                    'delete' => ['DELETE'],
 | 
			
		||||
                    'reset' => ['POST'],
 | 
			
		||||
                    'get-per-account' => ['GET'],
 | 
			
		||||
                    'get-authorized-clients' => ['GET'],
 | 
			
		||||
                    'revoke-client' => ['DELETE'],
 | 
			
		||||
                ],
 | 
			
		||||
            ],
 | 
			
		||||
        ]);
 | 
			
		||||
@@ -128,18 +148,60 @@ class ClientsController extends Controller {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function actionGetPerAccount(int $accountId): array {
 | 
			
		||||
        /** @var Account|null $account */
 | 
			
		||||
        $account = Account::findOne(['id' => $accountId]);
 | 
			
		||||
        if ($account === null) {
 | 
			
		||||
            throw new NotFoundHttpException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /** @var OauthClient[] $clients */
 | 
			
		||||
        $clients = $account->getOauthClients()->orderBy(['created_at' => SORT_ASC])->all();
 | 
			
		||||
        $clients = $this->findAccount($accountId)->getOauthClients()->orderBy(['created_at' => SORT_ASC])->all();
 | 
			
		||||
 | 
			
		||||
        return array_map(fn(OauthClient $client): array => $this->formatClient($client), $clients);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function actionGetAuthorizedClients(int $accountId): array {
 | 
			
		||||
        $account = $this->findAccount($accountId);
 | 
			
		||||
 | 
			
		||||
        $result = [];
 | 
			
		||||
        /** @var \common\models\OauthSession[] $oauthSessions */
 | 
			
		||||
        $oauthSessions = $account->getOauthSessions()
 | 
			
		||||
            ->innerJoinWith(['client c' => function(ActiveQuery $query): void {
 | 
			
		||||
                $query->andOnCondition(['c.type' => OauthClient::TYPE_APPLICATION]);
 | 
			
		||||
            }])
 | 
			
		||||
            ->andWhere([
 | 
			
		||||
                'OR',
 | 
			
		||||
                ['revoked_at' => null],
 | 
			
		||||
                ['>', 'last_used_at', new Expression('`revoked_at`')],
 | 
			
		||||
            ])
 | 
			
		||||
            ->all();
 | 
			
		||||
        foreach ($oauthSessions as $oauthSession) {
 | 
			
		||||
            $client = $oauthSession->client;
 | 
			
		||||
            if ($client === null) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $result[] = [
 | 
			
		||||
                'id' => $client->id,
 | 
			
		||||
                'name' => $client->name,
 | 
			
		||||
                'description' => $client->description,
 | 
			
		||||
                'scopes' => $oauthSession->getScopes(),
 | 
			
		||||
                'authorizedAt' => $oauthSession->created_at,
 | 
			
		||||
                'lastUsedAt' => $oauthSession->last_used_at,
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function actionRevokeClient(int $accountId, string $clientId): ?array {
 | 
			
		||||
        $account = $this->findAccount($accountId);
 | 
			
		||||
        $client = $this->findOauthClient($clientId);
 | 
			
		||||
 | 
			
		||||
        /** @var \common\models\OauthSession|null $session */
 | 
			
		||||
        $session = $account->getOauthSessions()->andWhere(['client_id' => $client->id])->one();
 | 
			
		||||
        if ($session !== null && !$session->isRevoked()) {
 | 
			
		||||
            $session->revoked_at = time();
 | 
			
		||||
            Assert::true($session->save());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ['success' => true];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function formatClient(OauthClient $client): array {
 | 
			
		||||
        $result = [
 | 
			
		||||
            'clientId' => $client->id,
 | 
			
		||||
@@ -168,16 +230,26 @@ class ClientsController extends Controller {
 | 
			
		||||
        try {
 | 
			
		||||
            $model = OauthClientFormFactory::create($client);
 | 
			
		||||
        } catch (UnsupportedOauthClientType $e) {
 | 
			
		||||
            Yii::warning('Someone tried use ' . $client->type . ' type of oauth form.');
 | 
			
		||||
            Yii::warning('Someone tried to use ' . $client->type . ' type of oauth form.');
 | 
			
		||||
            throw new NotFoundHttpException(null, 0, $e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $model;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function findAccount(int $id): Account {
 | 
			
		||||
        /** @var Account|null $account */
 | 
			
		||||
        $account = Account::findOne(['id' => $id]);
 | 
			
		||||
        if ($account === null) {
 | 
			
		||||
            throw new NotFoundHttpException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $account;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function findOauthClient(string $clientId): OauthClient {
 | 
			
		||||
        /** @var OauthClient|null $client */
 | 
			
		||||
        $client = OauthClient::findOne($clientId);
 | 
			
		||||
        $client = OauthClient::findOne(['id' => $clientId]);
 | 
			
		||||
        if ($client === null) {
 | 
			
		||||
            throw new NotFoundHttpException();
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -223,6 +223,10 @@ class OauthProcess {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($session->isRevoked()) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return empty(array_diff($this->getScopesList($request), $session->getScopes()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -235,6 +239,7 @@ class OauthProcess {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $session->scopes = array_unique(array_merge($session->getScopes(), $this->getScopesList($request)));
 | 
			
		||||
        $session->last_used_at = time();
 | 
			
		||||
 | 
			
		||||
        Assert::true($session->save());
 | 
			
		||||
    }
 | 
			
		||||
@@ -346,7 +351,6 @@ class OauthProcess {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function findOauthSession(Account $account, OauthClient $client): ?OauthSession {
 | 
			
		||||
        /** @noinspection PhpIncompatibleReturnTypeInspection */
 | 
			
		||||
        return $account->getOauthSessions()->andWhere(['client_id' => $client->id])->one();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ final class Permissions {
 | 
			
		||||
    public const RESTORE_ACCOUNT = 'restore_account';
 | 
			
		||||
    public const BLOCK_ACCOUNT = 'block_account';
 | 
			
		||||
    public const COMPLETE_OAUTH_FLOW = 'complete_oauth_flow';
 | 
			
		||||
    public const MANAGE_OAUTH_SESSIONS = 'manage_oauth_sessions';
 | 
			
		||||
    public const CREATE_OAUTH_CLIENTS = 'create_oauth_clients';
 | 
			
		||||
    public const VIEW_OAUTH_CLIENTS = 'view_oauth_clients';
 | 
			
		||||
    public const MANAGE_OAUTH_CLIENTS = 'manage_oauth_clients';
 | 
			
		||||
@@ -32,6 +33,7 @@ final class Permissions {
 | 
			
		||||
    public const DELETE_OWN_ACCOUNT = 'delete_own_account';
 | 
			
		||||
    public const RESTORE_OWN_ACCOUNT = 'restore_own_account';
 | 
			
		||||
    public const MINECRAFT_SERVER_SESSION = 'minecraft_server_session';
 | 
			
		||||
    public const MANAGE_OWN_OAUTH_SESSIONS = 'manage_own_oauth_sessions';
 | 
			
		||||
    public const VIEW_OWN_OAUTH_CLIENTS = 'view_own_oauth_clients';
 | 
			
		||||
    public const MANAGE_OWN_OAUTH_CLIENTS = 'manage_own_oauth_clients';
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								api/tests/functional/accounts/GetAuthorizedClientsCest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								api/tests/functional/accounts/GetAuthorizedClientsCest.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
<?php
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace api\tests\functional\accounts;
 | 
			
		||||
 | 
			
		||||
use api\tests\FunctionalTester;
 | 
			
		||||
 | 
			
		||||
class GetAuthorizedClientsCest {
 | 
			
		||||
 | 
			
		||||
    public function testGet(FunctionalTester $I) {
 | 
			
		||||
        $id = $I->amAuthenticated('admin');
 | 
			
		||||
        $I->sendGET("/api/v1/accounts/{$id}/oauth2/authorized");
 | 
			
		||||
        $I->canSeeResponseCodeIs(200);
 | 
			
		||||
        $I->canSeeResponseIsJson();
 | 
			
		||||
        $I->canSeeResponseContainsJson([
 | 
			
		||||
            [
 | 
			
		||||
                'id' => 'test1',
 | 
			
		||||
                'name' => 'Test1',
 | 
			
		||||
                'description' => 'Some description',
 | 
			
		||||
                'scopes' => ['minecraft_server_session', 'obtain_own_account_info'],
 | 
			
		||||
                'authorizedAt' => 1479944472,
 | 
			
		||||
                'lastUsedAt' => 1479944472,
 | 
			
		||||
            ],
 | 
			
		||||
        ]);
 | 
			
		||||
        $I->cantSeeResponseJsonMatchesJsonPath('$.[?(@.id="tlauncher")]');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testGetForNotOwnIdentity(FunctionalTester $I) {
 | 
			
		||||
        $I->amAuthenticated('admin');
 | 
			
		||||
        $I->sendGET('/api/v1/accounts/2/oauth2/authorized');
 | 
			
		||||
        $I->canSeeResponseCodeIs(403);
 | 
			
		||||
        $I->canSeeResponseContainsJson([
 | 
			
		||||
            'name' => 'Forbidden',
 | 
			
		||||
            'message' => 'You are not allowed to perform this action.',
 | 
			
		||||
            'code' => 0,
 | 
			
		||||
            'status' => 403,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								api/tests/functional/accounts/RevokeAuthorizedClientCest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								api/tests/functional/accounts/RevokeAuthorizedClientCest.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
<?php
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace api\tests\functional\accounts;
 | 
			
		||||
 | 
			
		||||
use api\tests\FunctionalTester;
 | 
			
		||||
 | 
			
		||||
class RevokeAuthorizedClientCest {
 | 
			
		||||
 | 
			
		||||
    public function testRevokeAuthorizedClient(FunctionalTester $I) {
 | 
			
		||||
        $id = $I->amAuthenticated('admin');
 | 
			
		||||
        $I->sendDELETE("/api/v1/accounts/{$id}/oauth2/authorized/test1");
 | 
			
		||||
        $I->canSeeResponseCodeIs(200);
 | 
			
		||||
        $I->canSeeResponseIsJson();
 | 
			
		||||
        $I->canSeeResponseContainsJson([
 | 
			
		||||
            'success' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $I->sendGET("/api/v1/accounts/{$id}/oauth2/authorized");
 | 
			
		||||
        $I->cantSeeResponseJsonMatchesJsonPath('$.[?(@.id="test1")]');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testRevokeAlreadyRevokedClient(FunctionalTester $I) {
 | 
			
		||||
        $id = $I->amAuthenticated('admin');
 | 
			
		||||
        $I->sendDELETE("/api/v1/accounts/{$id}/oauth2/authorized/tlauncher");
 | 
			
		||||
        $I->canSeeResponseCodeIs(200);
 | 
			
		||||
        $I->canSeeResponseIsJson();
 | 
			
		||||
        $I->canSeeResponseContainsJson([
 | 
			
		||||
            'success' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testRevokeForNotOwnIdentity(FunctionalTester $I) {
 | 
			
		||||
        $I->amAuthenticated('admin');
 | 
			
		||||
        $I->sendDELETE('/api/v1/accounts/2/oauth2/authorized/test1');
 | 
			
		||||
        $I->canSeeResponseCodeIs(403);
 | 
			
		||||
        $I->canSeeResponseContainsJson([
 | 
			
		||||
            'name' => 'Forbidden',
 | 
			
		||||
            'message' => 'You are not allowed to perform this action.',
 | 
			
		||||
            'code' => 0,
 | 
			
		||||
            'status' => 403,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -16,10 +16,14 @@ use yii\db\ActiveRecord;
 | 
			
		||||
 * @property array $scopes
 | 
			
		||||
 * @property int $created_at
 | 
			
		||||
 * @property int|null $revoked_at
 | 
			
		||||
 * @property int $last_used_at
 | 
			
		||||
 *
 | 
			
		||||
 * Relations:
 | 
			
		||||
 * @property-read OauthClient $client
 | 
			
		||||
 * @property-read OauthClient|null $client
 | 
			
		||||
 * @property-read Account $account
 | 
			
		||||
 *
 | 
			
		||||
 * Mixins:
 | 
			
		||||
 * @mixin TimestampBehavior
 | 
			
		||||
 */
 | 
			
		||||
class OauthSession extends ActiveRecord {
 | 
			
		||||
 | 
			
		||||
@@ -36,6 +40,10 @@ class OauthSession extends ActiveRecord {
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function isRevoked(): bool {
 | 
			
		||||
        return $this->revoked_at > $this->last_used_at;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getClient(): ActiveQuery {
 | 
			
		||||
        return $this->hasOne(OauthClient::class, ['id' => 'client_id']);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ return [
 | 
			
		||||
        'scopes' => null,
 | 
			
		||||
        'created_at' => 1479944472,
 | 
			
		||||
        'revoked_at' => null,
 | 
			
		||||
        'last_used_at' => 1479944472,
 | 
			
		||||
    ],
 | 
			
		||||
    'revoked-tlauncher' => [
 | 
			
		||||
        'account_id' => 1,
 | 
			
		||||
@@ -15,6 +16,7 @@ return [
 | 
			
		||||
        'scopes' => null,
 | 
			
		||||
        'created_at' => Carbon\Carbon::create(2019, 8, 1, 0, 0, 0, 'Europe/Minsk')->unix(),
 | 
			
		||||
        'revoked_at' => Carbon\Carbon::create(2019, 8, 1, 1, 2, 0, 'Europe/Minsk')->unix(),
 | 
			
		||||
        'last_used_at' => Carbon\Carbon::create(2019, 8, 1, 0, 0, 0, 'Europe/Minsk')->unix(),
 | 
			
		||||
    ],
 | 
			
		||||
    'revoked-minecraft-game-launchers' => [
 | 
			
		||||
        'account_id' => 1,
 | 
			
		||||
@@ -23,6 +25,7 @@ return [
 | 
			
		||||
        'scopes' => null,
 | 
			
		||||
        'created_at' => Carbon\Carbon::create(2019, 8, 1, 0, 0, 0, 'Europe/Minsk')->unix(),
 | 
			
		||||
        'revoked_at' => Carbon\Carbon::create(2019, 8, 1, 1, 2, 0, 'Europe/Minsk')->unix(),
 | 
			
		||||
        'last_used_at' => Carbon\Carbon::create(2019, 8, 1, 0, 0, 0, 'Europe/Minsk')->unix(),
 | 
			
		||||
    ],
 | 
			
		||||
    'banned-account-session' => [
 | 
			
		||||
        'account_id' => 10,
 | 
			
		||||
@@ -31,6 +34,7 @@ return [
 | 
			
		||||
        'scopes' => null,
 | 
			
		||||
        'created_at' => 1481421663,
 | 
			
		||||
        'revoked_at' => null,
 | 
			
		||||
        'last_used_at' => 1481421663,
 | 
			
		||||
    ],
 | 
			
		||||
    'deleted-client-session' => [
 | 
			
		||||
        'account_id' => 1,
 | 
			
		||||
@@ -39,6 +43,7 @@ return [
 | 
			
		||||
        'scopes' => null,
 | 
			
		||||
        'created_at' => 1519510065,
 | 
			
		||||
        'revoked_at' => null,
 | 
			
		||||
        'last_used_at' => 1519510065,
 | 
			
		||||
    ],
 | 
			
		||||
    'actual-deleted-client-session' => [
 | 
			
		||||
        'account_id' => 2,
 | 
			
		||||
@@ -47,5 +52,6 @@ return [
 | 
			
		||||
        'scopes' => null,
 | 
			
		||||
        'created_at' => 1519511568,
 | 
			
		||||
        'revoked_at' => null,
 | 
			
		||||
        'last_used_at' => 1519511568,
 | 
			
		||||
    ],
 | 
			
		||||
];
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,7 @@ class RbacController extends Controller {
 | 
			
		||||
        $permViewOauthClients = $this->createPermission(P::VIEW_OAUTH_CLIENTS);
 | 
			
		||||
        $permManageOauthClients = $this->createPermission(P::MANAGE_OAUTH_CLIENTS);
 | 
			
		||||
        $permCompleteOauthFlow = $this->createPermission(P::COMPLETE_OAUTH_FLOW, AccountOwner::class);
 | 
			
		||||
        $permManageOauthSessions = $this->createPermission(P::MANAGE_OAUTH_SESSIONS);
 | 
			
		||||
 | 
			
		||||
        $permObtainAccountEmail = $this->createPermission(P::OBTAIN_ACCOUNT_EMAIL);
 | 
			
		||||
        $permObtainExtendedAccountInfo = $this->createPermission(P::OBTAIN_EXTENDED_ACCOUNT_INFO);
 | 
			
		||||
@@ -53,6 +54,7 @@ class RbacController extends Controller {
 | 
			
		||||
        $permDeleteOwnAccount = $this->createPermission(P::DELETE_OWN_ACCOUNT, AccountOwner::class);
 | 
			
		||||
        $permRestoreOwnAccount = $this->createPermission(P::RESTORE_OWN_ACCOUNT, AccountOwner::class);
 | 
			
		||||
        $permMinecraftServerSession = $this->createPermission(P::MINECRAFT_SERVER_SESSION);
 | 
			
		||||
        $permManageOwnOauthSessions = $this->createPermission(P::MANAGE_OWN_OAUTH_SESSIONS, AccountOwner::class);
 | 
			
		||||
        $permViewOwnOauthClients = $this->createPermission(P::VIEW_OWN_OAUTH_CLIENTS, OauthClientOwner::class);
 | 
			
		||||
        $permManageOwnOauthClients = $this->createPermission(P::MANAGE_OWN_OAUTH_CLIENTS, OauthClientOwner::class);
 | 
			
		||||
 | 
			
		||||
@@ -69,6 +71,7 @@ class RbacController extends Controller {
 | 
			
		||||
        $authManager->addChild($permManageOwnTwoFactorAuth, $permManageTwoFactorAuth);
 | 
			
		||||
        $authManager->addChild($permDeleteOwnAccount, $permDeleteAccount);
 | 
			
		||||
        $authManager->addChild($permRestoreOwnAccount, $permRestoreAccount);
 | 
			
		||||
        $authManager->addChild($permManageOwnOauthSessions, $permManageOauthSessions);
 | 
			
		||||
        $authManager->addChild($permViewOwnOauthClients, $permViewOauthClients);
 | 
			
		||||
        $authManager->addChild($permManageOwnOauthClients, $permManageOauthClients);
 | 
			
		||||
 | 
			
		||||
@@ -86,6 +89,7 @@ class RbacController extends Controller {
 | 
			
		||||
        $authManager->addChild($roleAccountsWebUser, $permRestoreOwnAccount);
 | 
			
		||||
        $authManager->addChild($roleAccountsWebUser, $permCompleteOauthFlow);
 | 
			
		||||
        $authManager->addChild($roleAccountsWebUser, $permCreateOauthClients);
 | 
			
		||||
        $authManager->addChild($roleAccountsWebUser, $permManageOwnOauthSessions);
 | 
			
		||||
        $authManager->addChild($roleAccountsWebUser, $permViewOwnOauthClients);
 | 
			
		||||
        $authManager->addChild($roleAccountsWebUser, $permManageOwnOauthClients);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,19 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
use console\db\Migration;
 | 
			
		||||
use yii\db\Expression;
 | 
			
		||||
 | 
			
		||||
class m200925_224423_add_oauth_sessions_last_used_at_column extends Migration {
 | 
			
		||||
 | 
			
		||||
    public function safeUp() {
 | 
			
		||||
        $this->addColumn('oauth_sessions', 'last_used_at', $this->integer(11)->unsigned()->notNull());
 | 
			
		||||
        $this->update('oauth_sessions', [
 | 
			
		||||
            'last_used_at' => new Expression('`created_at`'),
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function safeDown() {
 | 
			
		||||
        $this->dropColumn('oauth_sessions', 'last_used_at');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user