mirror of
https://github.com/elyby/accounts.git
synced 2024-12-23 13:50:06 +05:30
Covered all cases, fixed CS, added a new TODO
This commit is contained in:
parent
0183e54442
commit
17f1794a4e
@ -62,14 +62,10 @@ class RefreshTokenForm extends ApiForm {
|
||||
$account = Account::findOne(['id' => $tokenReader->getAccountId()]);
|
||||
}
|
||||
|
||||
if ($account === null || $account->status === Account::STATUS_DELETED) {
|
||||
if ($account === null) {
|
||||
throw new ForbiddenOperationException('Invalid token.');
|
||||
}
|
||||
|
||||
if ($account->status === Account::STATUS_BANNED) {
|
||||
throw new ForbiddenOperationException('This account has been suspended.');
|
||||
}
|
||||
|
||||
$token = Yii::$app->tokensFactory->createForMinecraftAccount($account, $this->clientToken);
|
||||
|
||||
// TODO: This behavior duplicates with the AuthenticationForm. Need to find a way to avoid duplication.
|
||||
|
@ -3,18 +3,24 @@ declare(strict_types=1);
|
||||
|
||||
namespace api\modules\authserver\validators;
|
||||
|
||||
use api\components\Tokens\TokenReader;
|
||||
use api\modules\authserver\exceptions\ForbiddenOperationException;
|
||||
use Carbon\Carbon;
|
||||
use common\models\Account;
|
||||
use common\models\MinecraftAccessKey;
|
||||
use Exception;
|
||||
use Lcobucci\JWT\ValidationData;
|
||||
use Yii;
|
||||
use yii\validators\Validator;
|
||||
|
||||
class AccessTokenValidator extends Validator {
|
||||
|
||||
private const INVALID_TOKEN = 'Invalid token.';
|
||||
private const TOKEN_EXPIRED = 'Token expired.';
|
||||
|
||||
public bool $verifyExpiration = true;
|
||||
|
||||
public bool $verifyAccount = true;
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
@ -29,15 +35,19 @@ class AccessTokenValidator extends Validator {
|
||||
try {
|
||||
$token = Yii::$app->tokens->parse($value);
|
||||
} catch (Exception $e) {
|
||||
throw new ForbiddenOperationException('Invalid token.');
|
||||
throw new ForbiddenOperationException(self::INVALID_TOKEN);
|
||||
}
|
||||
|
||||
if (!Yii::$app->tokens->verify($token)) {
|
||||
throw new ForbiddenOperationException('Invalid token.');
|
||||
throw new ForbiddenOperationException(self::INVALID_TOKEN);
|
||||
}
|
||||
|
||||
if ($this->verifyExpiration && !$token->validate(new ValidationData(Carbon::now()->getTimestamp()))) {
|
||||
throw new ForbiddenOperationException('Token expired.');
|
||||
if ($this->verifyExpiration && $token->isExpired(Carbon::now())) {
|
||||
throw new ForbiddenOperationException(self::TOKEN_EXPIRED);
|
||||
}
|
||||
|
||||
if ($this->verifyAccount && !$this->validateAccount((new TokenReader($token))->getAccountId())) {
|
||||
throw new ForbiddenOperationException(self::INVALID_TOKEN);
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -53,14 +63,25 @@ class AccessTokenValidator extends Validator {
|
||||
/** @var MinecraftAccessKey|null $result */
|
||||
$result = MinecraftAccessKey::findOne(['access_token' => $value]);
|
||||
if ($result === null) {
|
||||
throw new ForbiddenOperationException('Invalid token.');
|
||||
throw new ForbiddenOperationException(self::INVALID_TOKEN);
|
||||
}
|
||||
|
||||
if ($this->verifyExpiration && $result->isExpired()) {
|
||||
throw new ForbiddenOperationException('Token expired.');
|
||||
throw new ForbiddenOperationException(self::TOKEN_EXPIRED);
|
||||
}
|
||||
|
||||
if ($this->verifyAccount && !$this->validateAccount($result->account_id)) {
|
||||
throw new ForbiddenOperationException(self::INVALID_TOKEN);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function validateAccount(int $accountId): bool {
|
||||
/** @var Account|null $account */
|
||||
$account = Account::find()->excludeDeleted()->andWhere(['id' => $accountId])->one();
|
||||
|
||||
return $account !== null && $account->status !== Account::STATUS_BANNED;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace api\tests\functional\accounts;
|
||||
|
||||
use api\tests\_pages\AccountsRoute;
|
||||
use api\tests\FunctionalTester;
|
||||
|
||||
class DeleteCest {
|
||||
|
@ -3,7 +3,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace api\tests\functional\accounts;
|
||||
|
||||
use api\tests\_pages\AccountsRoute;
|
||||
use api\tests\FunctionalTester;
|
||||
|
||||
class RestoreCest {
|
||||
|
@ -115,7 +115,7 @@ class RefreshCest {
|
||||
$I->canSeeResponseCodeIs(401);
|
||||
$I->canSeeResponseContainsJson([
|
||||
'error' => 'ForbiddenOperationException',
|
||||
'errorMessage' => 'This account has been suspended.',
|
||||
'errorMessage' => 'Invalid token.',
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ namespace common\models;
|
||||
use common\behaviors\PrimaryKeyValueBehavior;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use yii\behaviors\TimestampBehavior;
|
||||
use yii\db\ActiveQuery;
|
||||
use yii\db\ActiveRecord;
|
||||
|
||||
/**
|
||||
@ -52,7 +51,8 @@ class MinecraftAccessKey extends ActiveRecord {
|
||||
];
|
||||
}
|
||||
|
||||
public function getAccount(): ActiveQuery {
|
||||
public function getAccount(): AccountQuery {
|
||||
/** @noinspection PhpIncompatibleReturnTypeInspection */
|
||||
return $this->hasOne(Account::class, ['id' => 'account_id']);
|
||||
}
|
||||
|
||||
|
@ -54,4 +54,6 @@ class WebhooksController extends Controller {
|
||||
return ExitCode::OK;
|
||||
}
|
||||
|
||||
// TODO: add action to modify the webhook events
|
||||
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ class WebHookForm extends Model {
|
||||
public static function getEvents(): array {
|
||||
return [
|
||||
'account.edit',
|
||||
'account.deletion',
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user