mirror of
https://github.com/elyby/accounts.git
synced 2025-05-31 14:11:46 +05:30
Добавлен контроллер для блокировки аккаунта
Добавлен client_credentials grant для oAuth Рефакторинг структуры OauthScopes чтобы можно было разделить владельца прав на пользовательские и общие (машинные) Исправлена стилистика кода, внедряются фишки PHP 7.1
This commit is contained in:
@@ -6,8 +6,8 @@ use yii\web\User as YiiUserComponent;
|
||||
/**
|
||||
* @property Identity|null $identity
|
||||
*
|
||||
* @method Identity|null getIdentity()
|
||||
* @method Identity|null loginByAccessToken(string $token, $type = null)
|
||||
* @method Identity|null getIdentity($autoRenew = true)
|
||||
* @method Identity|null loginByAccessToken($token, $type = null)
|
||||
*/
|
||||
class Component extends YiiUserComponent {
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ class Identity implements IdentityInterface {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function findIdentityByAccessToken($token, $type = null) {
|
||||
public static function findIdentityByAccessToken($token, $type = null): self {
|
||||
/** @var AccessTokenEntity|null $model */
|
||||
$model = Yii::$app->oauth->getAuthServer()->getAccessTokenStorage()->get($token);
|
||||
if ($model === null) {
|
||||
throw new UnauthorizedHttpException('Incorrect token');
|
||||
@@ -41,19 +42,19 @@ class Identity implements IdentityInterface {
|
||||
$this->_accessToken = $accessToken;
|
||||
}
|
||||
|
||||
public function getAccount() : Account {
|
||||
public function getAccount(): Account {
|
||||
return $this->getSession()->account;
|
||||
}
|
||||
|
||||
public function getClient() : OauthClient {
|
||||
public function getClient(): OauthClient {
|
||||
return $this->getSession()->client;
|
||||
}
|
||||
|
||||
public function getSession() : OauthSession {
|
||||
public function getSession(): OauthSession {
|
||||
return OauthSession::findOne($this->_accessToken->getSessionId());
|
||||
}
|
||||
|
||||
public function getAccessToken() : AccessTokenEntity {
|
||||
public function getAccessToken(): AccessTokenEntity {
|
||||
return $this->_accessToken;
|
||||
}
|
||||
|
||||
@@ -62,7 +63,7 @@ class Identity implements IdentityInterface {
|
||||
* У нас права привязываются к токенам, так что возвращаем именно его id.
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getId() {
|
||||
public function getId(): string {
|
||||
return $this->_accessToken->getId();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ namespace api\components\OAuth2\Entities;
|
||||
|
||||
class ClientEntity extends \League\OAuth2\Server\Entity\ClientEntity {
|
||||
|
||||
private $isTrusted;
|
||||
|
||||
public function setId(string $id) {
|
||||
$this->id = $id;
|
||||
}
|
||||
@@ -19,4 +21,12 @@ class ClientEntity extends \League\OAuth2\Server\Entity\ClientEntity {
|
||||
$this->redirectUri = $redirectUri;
|
||||
}
|
||||
|
||||
public function setIsTrusted(bool $isTrusted) {
|
||||
$this->isTrusted = $isTrusted;
|
||||
}
|
||||
|
||||
public function isTrusted(): bool {
|
||||
return $this->isTrusted;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
20
api/components/OAuth2/Grants/ClientCredentialsGrant.php
Normal file
20
api/components/OAuth2/Grants/ClientCredentialsGrant.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace api\components\OAuth2\Grants;
|
||||
|
||||
use api\components\OAuth2\Entities;
|
||||
|
||||
class ClientCredentialsGrant extends \League\OAuth2\Server\Grant\ClientCredentialsGrant {
|
||||
|
||||
protected function createAccessTokenEntity() {
|
||||
return new Entities\AccessTokenEntity($this->server);
|
||||
}
|
||||
|
||||
protected function createRefreshTokenEntity() {
|
||||
return new Entities\RefreshTokenEntity($this->server);
|
||||
}
|
||||
|
||||
protected function createSessionEntity() {
|
||||
return new Entities\SessionEntity($this->server);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -74,6 +74,7 @@ class ClientStorage extends AbstractStorage implements ClientInterface {
|
||||
$entity->setId($model->id);
|
||||
$entity->setName($model->name);
|
||||
$entity->setSecret($model->secret);
|
||||
$entity->setIsTrusted($model->is_trusted);
|
||||
$entity->setRedirectUri($model->redirect_uri);
|
||||
|
||||
return $entity;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<?php
|
||||
namespace api\components\OAuth2\Storage;
|
||||
|
||||
use api\components\OAuth2\Entities\ClientEntity;
|
||||
use api\components\OAuth2\Entities\ScopeEntity;
|
||||
use common\models\OauthScope;
|
||||
use League\OAuth2\Server\Storage\AbstractStorage;
|
||||
use League\OAuth2\Server\Storage\ScopeInterface;
|
||||
use yii\base\ErrorException;
|
||||
|
||||
class ScopeStorage extends AbstractStorage implements ScopeInterface {
|
||||
|
||||
@@ -12,7 +14,27 @@ class ScopeStorage extends AbstractStorage implements ScopeInterface {
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($scope, $grantType = null, $clientId = null) {
|
||||
$scopes = $grantType === 'authorization_code' ? OauthScope::getPublicScopes() : OauthScope::getScopes();
|
||||
$query = OauthScope::find();
|
||||
if ($grantType === 'authorization_code') {
|
||||
$query->onlyPublic()->usersScopes();
|
||||
} elseif ($grantType === 'client_credentials') {
|
||||
$query->machineScopes();
|
||||
$isTrusted = false;
|
||||
if ($clientId !== null) {
|
||||
$client = $this->server->getClientStorage()->get($clientId);
|
||||
if (!$client instanceof ClientEntity) {
|
||||
throw new ErrorException('client storage must return instance of ' . ClientEntity::class);
|
||||
}
|
||||
|
||||
$isTrusted = $client->isTrusted();
|
||||
}
|
||||
|
||||
if (!$isTrusted) {
|
||||
$query->onlyPublic();
|
||||
}
|
||||
}
|
||||
|
||||
$scopes = $query->all();
|
||||
if (!in_array($scope, $scopes, true)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ $params = array_merge(
|
||||
return [
|
||||
'id' => 'accounts-site-api',
|
||||
'basePath' => dirname(__DIR__),
|
||||
'bootstrap' => ['log', 'authserver'],
|
||||
'bootstrap' => ['log', 'authserver', 'internal'],
|
||||
'controllerNamespace' => 'api\controllers',
|
||||
'params' => $params,
|
||||
'components' => [
|
||||
@@ -75,10 +75,11 @@ return [
|
||||
],
|
||||
'oauth' => [
|
||||
'class' => api\components\OAuth2\Component::class,
|
||||
'grantTypes' => ['authorization_code'],
|
||||
'grantTypes' => ['authorization_code', 'client_credentials'],
|
||||
'grantMap' => [
|
||||
'authorization_code' => api\components\OAuth2\Grants\AuthCodeGrant::class,
|
||||
'refresh_token' => api\components\OAuth2\Grants\RefreshTokenGrant::class,
|
||||
'client_credentials' => api\components\OAuth2\Grants\ClientCredentialsGrant::class,
|
||||
],
|
||||
],
|
||||
'errorHandler' => [
|
||||
@@ -96,5 +97,8 @@ return [
|
||||
'mojang' => [
|
||||
'class' => api\modules\mojang\Module::class,
|
||||
],
|
||||
'internal' => [
|
||||
'class' => api\modules\internal\Module::class,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -7,7 +7,9 @@ use api\components\OAuth2\Exception\AccessDeniedException;
|
||||
use common\models\Account;
|
||||
use common\models\OauthClient;
|
||||
use common\models\OauthScope;
|
||||
use League\OAuth2\Server\AuthorizationServer;
|
||||
use League\OAuth2\Server\Exception\OAuthException;
|
||||
use League\OAuth2\Server\Grant\AuthCodeGrant;
|
||||
use Yii;
|
||||
use yii\filters\AccessControl;
|
||||
use yii\helpers\ArrayHelper;
|
||||
@@ -274,17 +276,12 @@ class OauthController extends Controller {
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \League\OAuth2\Server\AuthorizationServer
|
||||
*/
|
||||
private function getServer() {
|
||||
private function getServer(): AuthorizationServer {
|
||||
return Yii::$app->oauth->authServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \League\OAuth2\Server\Grant\AuthCodeGrant
|
||||
*/
|
||||
private function getGrantType() {
|
||||
private function getGrantType(): AuthCodeGrant {
|
||||
/** @noinspection PhpIncompatibleReturnTypeInspection */
|
||||
return $this->getServer()->getGrantType('authorization_code');
|
||||
}
|
||||
|
||||
|
||||
19
api/modules/internal/Module.php
Normal file
19
api/modules/internal/Module.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
namespace api\modules\internal;
|
||||
|
||||
use yii\base\BootstrapInterface;
|
||||
|
||||
class Module extends \yii\base\Module implements BootstrapInterface {
|
||||
|
||||
public $id = 'internal';
|
||||
|
||||
/**
|
||||
* @param \yii\base\Application $app the application currently running
|
||||
*/
|
||||
public function bootstrap($app) {
|
||||
$app->getUrlManager()->addRules([
|
||||
'/internal/<controller>/<accountId>/<action>' => "{$this->id}/<controller>/<action>",
|
||||
], false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@ namespace api\modules\internal\controllers;
|
||||
|
||||
use api\components\ApiUser\AccessControl;
|
||||
use api\controllers\Controller;
|
||||
use api\modules\internal\models\BlockForm;
|
||||
use api\modules\internal\models\BanForm;
|
||||
use common\models\Account;
|
||||
use common\models\OauthScope as S;
|
||||
use Yii;
|
||||
@@ -14,11 +14,14 @@ class AccountsController extends Controller {
|
||||
|
||||
public function behaviors() {
|
||||
return ArrayHelper::merge(parent::behaviors(), [
|
||||
'authenticator' => [
|
||||
'user' => Yii::$app->apiUser,
|
||||
],
|
||||
'access' => [
|
||||
'class' => AccessControl::class,
|
||||
'rules' => [
|
||||
[
|
||||
'actions' => ['block'],
|
||||
'actions' => ['ban'],
|
||||
'allow' => true,
|
||||
'roles' => [S::ACCOUNT_BLOCK],
|
||||
],
|
||||
@@ -27,9 +30,9 @@ class AccountsController extends Controller {
|
||||
]);
|
||||
}
|
||||
|
||||
public function actionBlock(int $accountId) {
|
||||
public function actionBan(int $accountId) {
|
||||
$account = $this->findAccount($accountId);
|
||||
$model = new BlockForm($account);
|
||||
$model = new BanForm($account);
|
||||
$model->load(Yii::$app->request->post());
|
||||
if (!$model->ban()) {
|
||||
return [
|
||||
|
||||
8
api/modules/internal/helpers/Error.php
Normal file
8
api/modules/internal/helpers/Error.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
namespace api\modules\internal\helpers;
|
||||
|
||||
final class Error {
|
||||
|
||||
public const ACCOUNT_ALREADY_BANNED = 'error.account_already_banned';
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace api\modules\internal\models;
|
||||
|
||||
use api\models\base\ApiForm;
|
||||
use api\modules\internal\helpers\Error as E;
|
||||
use common\helpers\Amqp;
|
||||
use common\models\Account;
|
||||
use common\models\amqp\AccountBanned;
|
||||
@@ -9,14 +10,14 @@ use PhpAmqpLib\Message\AMQPMessage;
|
||||
use Yii;
|
||||
use yii\base\ErrorException;
|
||||
|
||||
class BlockForm extends ApiForm {
|
||||
class BanForm extends ApiForm {
|
||||
|
||||
const DURATION_FOREVER = -1;
|
||||
public const DURATION_FOREVER = -1;
|
||||
|
||||
/**
|
||||
* Нереализованный функционал блокировки аккаунта на определённый период времени.
|
||||
* Сейчас установка этого параметра ничего не даст, аккаунт будет заблокирован навечно,
|
||||
* но по задумке, здесь необходимо передать количество секунд, на которое будет
|
||||
* но, по задумке, здесь можно передать количество секунд, на которое будет
|
||||
* заблокирован аккаунт пользователя.
|
||||
*
|
||||
* @var int
|
||||
@@ -35,10 +36,11 @@ class BlockForm extends ApiForm {
|
||||
*/
|
||||
private $account;
|
||||
|
||||
public function rules() {
|
||||
public function rules(): array {
|
||||
return [
|
||||
[['duration'], 'integer', 'min' => self::DURATION_FOREVER],
|
||||
[['message'], 'string'],
|
||||
[['account'], 'validateAccountActivity'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -46,7 +48,17 @@ class BlockForm extends ApiForm {
|
||||
return $this->account;
|
||||
}
|
||||
|
||||
public function validateAccountActivity() {
|
||||
if ($this->account->status === Account::STATUS_BANNED) {
|
||||
$this->addError('account', E::ACCOUNT_ALREADY_BANNED);
|
||||
}
|
||||
}
|
||||
|
||||
public function ban(): bool {
|
||||
if (!$this->validate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$transaction = Yii::$app->db->beginTransaction();
|
||||
|
||||
$account = $this->account;
|
||||
@@ -62,7 +74,7 @@ class BlockForm extends ApiForm {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function createTask() {
|
||||
public function createTask(): void {
|
||||
$model = new AccountBanned();
|
||||
$model->accountId = $this->account->id;
|
||||
$model->duration = $this->duration;
|
||||
Reference in New Issue
Block a user