Merge branch 'develop'

This commit is contained in:
ErickSkrauch
2017-04-10 14:55:06 +03:00
12 changed files with 124 additions and 69 deletions

View File

@@ -24,6 +24,7 @@ use yii\web\User as YiiUserComponent;
* @property AccountIdentity|null $identity * @property AccountIdentity|null $identity
* *
* @method AccountIdentity|null loginByAccessToken($token, $type = null) * @method AccountIdentity|null loginByAccessToken($token, $type = null)
* @method AccountIdentity|null getIdentity($autoRenew = true)
*/ */
class Component extends YiiUserComponent { class Component extends YiiUserComponent {
@@ -44,8 +45,6 @@ class Component extends YiiUserComponent {
public $sessionTimeout = 'P7D'; public $sessionTimeout = 'P7D';
private $_identity;
public function init() { public function init() {
parent::init(); parent::init();
if (!$this->secret) { if (!$this->secret) {
@@ -53,24 +52,6 @@ class Component extends YiiUserComponent {
} }
} }
/**
* @param bool $autoRenew
* @return null|AccountIdentity
*/
public function getIdentity($autoRenew = true) {
$result = parent::getIdentity($autoRenew);
if ($result === null && $this->_identity !== false) {
$bearer = $this->getBearerToken();
if ($bearer !== null) {
$result = $this->loginByAccessToken($bearer);
}
$this->_identity = $result ?: false;
}
return $result;
}
/** /**
* @param IdentityInterface $identity * @param IdentityInterface $identity
* @param bool $rememberMe * @param bool $rememberMe

View File

@@ -24,7 +24,7 @@ return [
'/mojang/profiles/<uuid>/names' => 'mojang/api/usernames-by-uuid', '/mojang/profiles/<uuid>/names' => 'mojang/api/usernames-by-uuid',
'POST /mojang/profiles' => 'mojang/api/uuids-by-usernames', 'POST /mojang/profiles' => 'mojang/api/uuids-by-usernames',
"<protocol:http|https>://{$params['authserverHost']}/mojang/api/users/profiles/minecraft/<username>" => 'mojang/api/uuid-by-username', "//{$params['authserverHost']}/mojang/api/users/profiles/minecraft/<username>" => 'mojang/api/uuid-by-username',
"<protocol:http|https>://{$params['authserverHost']}/mojang/api/user/profiles/<uuid>/names" => 'mojang/api/usernames-by-uuid', "//{$params['authserverHost']}/mojang/api/user/profiles/<uuid>/names" => 'mojang/api/usernames-by-uuid',
"POST <protocol:http|https>://{$params['authserverHost']}/mojang/api/profiles/minecraft" => 'mojang/api/uuids-by-usernames', "POST //{$params['authserverHost']}/mojang/api/profiles/minecraft" => 'mojang/api/uuids-by-usernames',
]; ];

View File

@@ -10,7 +10,7 @@ class FeedbackController extends Controller {
public function behaviors() { public function behaviors() {
return ArrayHelper::merge(parent::behaviors(), [ return ArrayHelper::merge(parent::behaviors(), [
'authenticator' => [ 'authenticator' => [
'except' => ['index'], 'optional' => ['index'],
], ],
]); ]);
} }

View File

@@ -39,7 +39,7 @@ class Module extends \yii\base\Module implements BootstrapInterface {
*/ */
public function bootstrap($app) { public function bootstrap($app) {
$app->getUrlManager()->addRules([ $app->getUrlManager()->addRules([
"<protocol:http|https>://$this->host/$this->id/auth/<action>" => "$this->id/authentication/<action>", "//$this->host/$this->id/auth/<action>" => "$this->id/authentication/<action>",
], false); ], false);
} }

View File

@@ -9,6 +9,7 @@ use common\models\Account;
use common\models\OauthScope as S; use common\models\OauthScope as S;
use Yii; use Yii;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException; use yii\web\NotFoundHttpException;
class AccountsController extends Controller { class AccountsController extends Controller {
@@ -26,6 +27,11 @@ class AccountsController extends Controller {
'allow' => true, 'allow' => true,
'roles' => [S::ACCOUNT_BLOCK], 'roles' => [S::ACCOUNT_BLOCK],
], ],
[
'actions' => ['info'],
'allow' => true,
'roles' => [S::INTERNAL_ACCOUNT_INFO],
],
], ],
], ],
]); ]);
@@ -34,6 +40,7 @@ class AccountsController extends Controller {
public function verbs() { public function verbs() {
return [ return [
'ban' => ['POST', 'DELETE'], 'ban' => ['POST', 'DELETE'],
'info' => ['GET'],
]; ];
} }
@@ -46,6 +53,29 @@ class AccountsController extends Controller {
} }
} }
public function actionInfo(int $id = null, string $username = null, string $uuid = null) {
if ($id !== null) {
$account = Account::findOne($id);
} elseif ($username !== null) {
$account = Account::findOne(['username' => $username]);
} elseif ($uuid !== null) {
$account = Account::findOne(['uuid' => $uuid]);
} else {
throw new BadRequestHttpException('One of the required get params must be presented.');
}
if ($account === null) {
throw new NotFoundHttpException('User by provided param not found.');
}
return [
'id' => $account->id,
'uuid' => $account->uuid,
'email' => $account->email,
'username' => $account->username,
];
}
private function banAccount(Account $account) { private function banAccount(Account $account) {
$model = new BanForm($account); $model = new BanForm($account);
$model->load(Yii::$app->request->post()); $model->load(Yii::$app->request->post());

View File

@@ -1,6 +1,6 @@
<?php <?php
return [ return [
'version' => '1.1.8', 'version' => '1.1.9',
'vendorPath' => dirname(dirname(__DIR__)) . '/vendor', 'vendorPath' => dirname(dirname(__DIR__)) . '/vendor',
'components' => [ 'components' => [
'cache' => [ 'cache' => [

View File

@@ -28,6 +28,11 @@ class OauthScope {
* @owner machine * @owner machine
*/ */
const ACCOUNT_BLOCK = 'account_block'; const ACCOUNT_BLOCK = 'account_block';
/**
* @internal
* @owner machine
*/
const INTERNAL_ACCOUNT_INFO = 'internal_account_info';
public static function find(): OauthScopeQuery { public static function find(): OauthScopeQuery {
return new OauthScopeQuery(static::queryScopes()); return new OauthScopeQuery(static::queryScopes());

View File

@@ -15,7 +15,7 @@
"minimum-stability": "stable", "minimum-stability": "stable",
"require": { "require": {
"php": "^7.1", "php": "^7.1",
"yiisoft/yii2": "2.0.10", "yiisoft/yii2": "2.0.11.2",
"yiisoft/yii2-swiftmailer": "*", "yiisoft/yii2-swiftmailer": "*",
"ramsey/uuid": "^3.5.0", "ramsey/uuid": "^3.5.0",
"league/oauth2-server": "dev-improvements#fbaa9b0bd3d8050235ba7dde90f731764122bc20", "league/oauth2-server": "dev-improvements#fbaa9b0bd3d8050235ba7dde90f731764122bc20",

View File

@@ -17,8 +17,8 @@ class CleanupController extends Controller {
]; ];
} }
/** @var EmailActivation[] $expiredEmails */ /** @var \yii\db\BatchQueryResult|EmailActivation[] $expiredEmails */
$expiredEmails = $query->andWhere($conditions)->all(); $expiredEmails = $query->andWhere($conditions)->each();
foreach ($expiredEmails as $email) { foreach ($expiredEmails as $email) {
$email->delete(); $email->delete();
} }

View File

@@ -18,4 +18,9 @@ class InternalRoute extends BasePage {
$this->actor->sendDELETE($this->getUrl()); $this->actor->sendDELETE($this->getUrl());
} }
public function info(string $param, string $value) {
$this->route = '/internal/accounts/info';
$this->actor->sendGET($this->getUrl(), [$param => $value]);
}
} }

View File

@@ -0,0 +1,74 @@
<?php
namespace tests\codeception\api\functional\internal;
use common\models\OauthScope as S;
use tests\codeception\api\_pages\InternalRoute;
use tests\codeception\api\functional\_steps\OauthSteps;
use tests\codeception\api\FunctionalTester;
class InfoCest {
/**
* @var InternalRoute
*/
private $route;
public function _before(FunctionalTester $I) {
$this->route = new InternalRoute($I);
}
public function testGetInfoById(OauthSteps $I) {
$accessToken = $I->getAccessTokenByClientCredentialsGrant([S::INTERNAL_ACCOUNT_INFO]);
$I->amBearerAuthenticated($accessToken);
$this->route->info('id', 1);
$this->expectSuccessResponse($I);
}
public function testGetInfoByUuid(OauthSteps $I) {
$accessToken = $I->getAccessTokenByClientCredentialsGrant([S::INTERNAL_ACCOUNT_INFO]);
$I->amBearerAuthenticated($accessToken);
$this->route->info('uuid', 'df936908-b2e1-544d-96f8-2977ec213022');
$this->expectSuccessResponse($I);
}
public function testGetInfoByUsername(OauthSteps $I) {
$accessToken = $I->getAccessTokenByClientCredentialsGrant([S::INTERNAL_ACCOUNT_INFO]);
$I->amBearerAuthenticated($accessToken);
$this->route->info('username', 'admin');
$this->expectSuccessResponse($I);
}
public function testInvalidParams(OauthSteps $I) {
$accessToken = $I->getAccessTokenByClientCredentialsGrant([S::INTERNAL_ACCOUNT_INFO]);
$I->amBearerAuthenticated($accessToken);
$this->route->info('', '');
$I->canSeeResponseCodeIs(400);
}
public function testAccountNotFound(OauthSteps $I) {
$accessToken = $I->getAccessTokenByClientCredentialsGrant([S::INTERNAL_ACCOUNT_INFO]);
$I->amBearerAuthenticated($accessToken);
$this->route->info('username', 'this-user-not-exists');
$I->canSeeResponseCodeIs(404);
}
/**
* @param OauthSteps $I
*/
private function expectSuccessResponse(OauthSteps $I): void {
$I->canSeeResponseCodeIs(200);
$I->canSeeResponseIsJson();
$I->canSeeResponseContainsJson([
'id' => 1,
'uuid' => 'df936908-b2e1-544d-96f8-2977ec213022',
'email' => 'admin@ely.by',
'username' => 'Admin',
]);
}
}

View File

@@ -41,46 +41,6 @@ class ComponentTest extends TestCase {
]; ];
} }
public function testGetIdentity() {
$this->specify('getIdentity should return null, if not authorization header', function() {
$this->mockAuthorizationHeader(null);
$this->assertNull($this->component->getIdentity());
});
$this->specify('getIdentity should return null, if passed bearer token don\'t return any account', function() {
$this->mockAuthorizationHeader('some-auth');
/** @var Component|\PHPUnit_Framework_MockObject_MockObject $component */
$component = $this->getMockBuilder(Component::class)
->setMethods(['loginByAccessToken'])
->setConstructorArgs([$this->getComponentArguments()])
->getMock();
$component
->expects($this->once())
->method('loginByAccessToken')
->willReturn(null);
$this->assertNull($component->getIdentity());
});
$this->specify('getIdentity should return identity from loginByAccessToken method', function() {
$identity = new AccountIdentity();
$this->mockAuthorizationHeader('some-auth');
/** @var Component|\PHPUnit_Framework_MockObject_MockObject $component */
$component = $this->getMockBuilder(Component::class)
->setMethods(['loginByAccessToken'])
->setConstructorArgs([$this->getComponentArguments()])
->getMock();
$component
->expects($this->once())
->method('loginByAccessToken')
->willReturn($identity);
$this->assertEquals($identity, $component->getIdentity());
});
}
public function testLogin() { public function testLogin() {
$this->mockRequest(); $this->mockRequest();
$this->specify('success get LoginResult object without session value', function() { $this->specify('success get LoginResult object without session value', function() {