diff --git a/api/config/config.php b/api/config/config.php index c00e318..d288abc 100644 --- a/api/config/config.php +++ b/api/config/config.php @@ -61,6 +61,9 @@ return [ ], 'request' => [ 'baseUrl' => '/api', + 'parsers' => [ + '*' => api\request\RequestParser::class, + ], ], 'urlManager' => [ 'enablePrettyUrl' => true, diff --git a/api/modules/authserver/controllers/AuthenticationController.php b/api/modules/authserver/controllers/AuthenticationController.php index 017549b..650928d 100644 --- a/api/modules/authserver/controllers/AuthenticationController.php +++ b/api/modules/authserver/controllers/AuthenticationController.php @@ -3,6 +3,7 @@ namespace api\modules\authserver\controllers; use api\controllers\Controller; use api\modules\authserver\models; +use Yii; class AuthenticationController extends Controller { @@ -25,21 +26,21 @@ class AuthenticationController extends Controller { public function actionAuthenticate() { $model = new models\AuthenticationForm(); - $model->loadByPost(); + $model->load(Yii::$app->request->post()); return $model->authenticate()->getResponseData(true); } public function actionRefresh() { $model = new models\RefreshTokenForm(); - $model->loadByPost(); + $model->load(Yii::$app->request->post()); return $model->refresh()->getResponseData(false); } public function actionValidate() { $model = new models\ValidateForm(); - $model->loadByPost(); + $model->load(Yii::$app->request->post()); $model->validateToken(); // В случае успеха ожидается пустой ответ. В случае ошибки же бросается исключение, // которое обработает ErrorHandler @@ -47,7 +48,7 @@ class AuthenticationController extends Controller { public function actionSignout() { $model = new models\SignoutForm(); - $model->loadByPost(); + $model->load(Yii::$app->request->post()); $model->signout(); // В случае успеха ожидается пустой ответ. В случае ошибки же бросается исключение, // которое обработает ErrorHandler @@ -55,7 +56,7 @@ class AuthenticationController extends Controller { public function actionInvalidate() { $model = new models\InvalidateForm(); - $model->loadByPost(); + $model->load(Yii::$app->request->post()); $model->invalidateToken(); // В случае успеха ожидается пустой ответ. В случае ошибки же бросается исключение, // которое обработает ErrorHandler diff --git a/api/modules/authserver/models/AuthenticationForm.php b/api/modules/authserver/models/AuthenticationForm.php index 14dd601..2a8b5dc 100644 --- a/api/modules/authserver/models/AuthenticationForm.php +++ b/api/modules/authserver/models/AuthenticationForm.php @@ -2,6 +2,7 @@ namespace api\modules\authserver\models; use api\models\authentication\LoginForm; +use api\models\base\ApiForm; use api\modules\authserver\exceptions\ForbiddenOperationException; use api\modules\authserver\Module as Authserver; use api\modules\authserver\validators\RequiredValidator; @@ -9,7 +10,7 @@ use common\helpers\Error as E; use common\models\Account; use common\models\MinecraftAccessKey; -class AuthenticationForm extends Form { +class AuthenticationForm extends ApiForm { public $username; public $password; diff --git a/api/modules/authserver/models/Form.php b/api/modules/authserver/models/Form.php deleted file mode 100644 index 02006d8..0000000 --- a/api/modules/authserver/models/Form.php +++ /dev/null @@ -1,27 +0,0 @@ -load(Yii::$app->request->get()); - } - - public function loadByPost() { - $data = Yii::$app->request->post(); - if (empty($data)) { - // TODO: помнится у Yii2 есть механизм парсинга данных входящего запроса. Лучше будет сделать это там - $data = json_decode(Yii::$app->request->getRawBody(), true); - } - - return $this->load($data); - } - -} diff --git a/api/modules/authserver/models/InvalidateForm.php b/api/modules/authserver/models/InvalidateForm.php index 7d0d7d0..a81e0ef 100644 --- a/api/modules/authserver/models/InvalidateForm.php +++ b/api/modules/authserver/models/InvalidateForm.php @@ -1,10 +1,11 @@ request->post(); if (empty($usernames)) { - $usernames = json_decode(Yii::$app->request->getRawBody()); - if (empty($usernames)) { - return $this->illegalArgumentResponse('Passed array of profile names is an invalid JSON string.'); - } + return $this->illegalArgumentResponse('Passed array of profile names is an invalid JSON string.'); } $usernames = array_unique($usernames); diff --git a/api/modules/session/controllers/SessionController.php b/api/modules/session/controllers/SessionController.php index 384d2f6..046b7ee 100644 --- a/api/modules/session/controllers/SessionController.php +++ b/api/modules/session/controllers/SessionController.php @@ -35,11 +35,6 @@ class SessionController extends ApiController { Yii::$app->response->format = Response::FORMAT_JSON; $data = Yii::$app->request->post(); - if (empty($data)) { - // TODO: помнится у Yii2 есть механизм парсинга данных входящего запроса. Лучше будет сделать это там - $data = json_decode(Yii::$app->request->getRawBody(), true); - } - $protocol = new ModernJoin($data['accessToken'] ?? '', $data['selectedProfile'] ?? '', $data['serverId'] ?? ''); $joinForm = new JoinForm($protocol); $joinForm->join(); diff --git a/api/request/RequestParser.php b/api/request/RequestParser.php new file mode 100644 index 0000000..614a5fe --- /dev/null +++ b/api/request/RequestParser.php @@ -0,0 +1,43 @@ +throwException = false; + $result = $parser->parse($rawBody, $contentType); + if (!empty($result)) { + return $result; + } + + mb_parse_str($rawBody, $bodyParams); + if (!empty($bodyParams)) { + return $bodyParams; + } + + return []; + } + +} diff --git a/tests/codeception/api/functional/authserver/AuthorizationCest.php b/tests/codeception/api/functional/authserver/AuthorizationCest.php index 7148e9a..626adb6 100644 --- a/tests/codeception/api/functional/authserver/AuthorizationCest.php +++ b/tests/codeception/api/functional/authserver/AuthorizationCest.php @@ -38,6 +38,17 @@ class AuthorizationCest { $this->testSuccessResponse($I); } + public function byNamePassedViaPOSTBody(FunctionalTester $I) { + $I->wantTo('authenticate by username and password sent via post body'); + $this->route->authenticate(json_encode([ + 'username' => 'admin', + 'password' => 'password_0', + 'clientToken' => Uuid::uuid4()->toString(), + ])); + + $this->testSuccessResponse($I); + } + public function byEmailWithEnabledTwoFactorAuth(FunctionalTester $I) { $I->wantTo('get valid error by authenticate account with enabled two factor auth'); $this->route->authenticate([ diff --git a/tests/codeception/api/functional/mojang/UsernamesToUuidsCest.php b/tests/codeception/api/functional/mojang/UsernamesToUuidsCest.php index caa42dd..6c871c5 100644 --- a/tests/codeception/api/functional/mojang/UsernamesToUuidsCest.php +++ b/tests/codeception/api/functional/mojang/UsernamesToUuidsCest.php @@ -98,17 +98,6 @@ class UsernamesToUuidsCest { ]); } - public function passWrongPostBody(FunctionalTester $I) { - $I->wantTo('get specific response when pass invalid json string'); - $this->route->uuidsByUsernames('wrong-json'); - $I->canSeeResponseCodeIs(400); - $I->canSeeResponseIsJson(); - $I->canSeeResponseContainsJson([ - 'error' => 'IllegalArgumentException', - 'errorMessage' => 'Passed array of profile names is an invalid JSON string.', - ]); - } - private function validateFewValidUsernames(FunctionalTester $I) { $I->canSeeResponseCodeIs(200); $I->canSeeResponseIsJson(); diff --git a/tests/codeception/api/unit/request/RequestParserTest.php b/tests/codeception/api/unit/request/RequestParserTest.php new file mode 100644 index 0000000..8dbb3e0 --- /dev/null +++ b/tests/codeception/api/unit/request/RequestParserTest.php @@ -0,0 +1,20 @@ + 'post']; + $this->assertEquals(['from' => 'post'], $parser->parse('from=post', '')); + $this->assertEquals(['from' => 'post'], $parser->parse('', '')); + $_POST = []; + $this->assertEquals(['from' => 'json'], $parser->parse('{"from":"json"}', '')); + $this->assertEquals(['from' => 'body'], $parser->parse('from=body', '')); + $this->assertEquals(['onlykey' => ''], $parser->parse('onlykey', '')); + } + +}