diff --git a/api/modules/mojang/behaviors/ServiceErrorConverterBehavior.php b/api/modules/mojang/behaviors/ServiceErrorConverterBehavior.php new file mode 100644 index 0000000..ad20134 --- /dev/null +++ b/api/modules/mojang/behaviors/ServiceErrorConverterBehavior.php @@ -0,0 +1,54 @@ + Closure::fromCallable([$this, 'beforeSend']), + ]; + } + + private function beforeSend(Event $event): void { + /** @var Response $response */ + $response = $event->sender; + $data = $response->data; + if ($data === null || !isset($data['status'])) { + return; + } + + $request = Yii::$app->request; + $type = $data['type']; + switch ($type) { + case UnauthorizedHttpException::class: + $response->data = [ + 'path' => '/' . $request->getPathInfo(), + 'errorType' => 'UnauthorizedOperationException', + 'error' => 'UnauthorizedOperationException', + 'errorMessage' => 'Unauthorized', + 'developerMessage' => 'Unauthorized', + ]; + break; + case NotFoundHttpException::class: + $response->data = [ + 'path' => '/' . $request->getPathInfo(), + 'errorType' => 'NOT_FOUND', + 'error' => 'NOT_FOUND', + 'errorMessage' => 'The server has not found anything matching the request URI', + 'developerMessage' => 'The server has not found anything matching the request URI', + ]; + break; + } + } + +} diff --git a/api/modules/mojang/controllers/ServicesController.php b/api/modules/mojang/controllers/ServicesController.php index 71654e2..a6e8b3e 100644 --- a/api/modules/mojang/controllers/ServicesController.php +++ b/api/modules/mojang/controllers/ServicesController.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace api\modules\mojang\controllers; use api\controllers\Controller; +use api\modules\mojang\behaviors\ServiceErrorConverterBehavior; use api\rbac\Permissions; use common\components\SkinsSystemApi; use Exception; @@ -12,6 +13,7 @@ use Yii; use yii\filters\AccessControl; use yii\filters\VerbFilter; use yii\helpers\ArrayHelper; +use yii\web\NotFoundHttpException; use function Ramsey\Uuid\v3; final class ServicesController extends Controller { @@ -44,9 +46,16 @@ final class ServicesController extends Controller { ]); } + public function init(): void { + parent::init(); + $this->response->attachBehavior('errorFormatter', ServiceErrorConverterBehavior::class); + } + public function actionProfile(SkinsSystemApi $skinsSystemApi): array { - /** @var \common\models\Account $account at this point null value isn't possible */ $account = Yii::$app->user->identity->getAccount(); + if ($account === null) { + throw new NotFoundHttpException(); + } try { $textures = $skinsSystemApi->textures($account->username); diff --git a/api/tests/functional/mojang/ProfileCest.php b/api/tests/functional/mojang/ProfileCest.php index 6925a4e..c677566 100644 --- a/api/tests/functional/mojang/ProfileCest.php +++ b/api/tests/functional/mojang/ProfileCest.php @@ -3,15 +3,15 @@ declare(strict_types=1); namespace api\tests\functional\mojang; +use api\tests\functional\_steps\OauthSteps; use api\tests\FunctionalTester; -class ProfileCest { +final class ProfileCest { public function getProfile(FunctionalTester $I): void { $I->amAuthenticated(); $I->sendGet('/api/mojang/services/minecraft/profile'); $I->canSeeResponseCodeIs(200); - $I->canSeeResponseIsJson(); $I->canSeeResponseContainsJson([ 'id' => 'df936908b2e1544d96f82977ec213022', 'name' => 'Admin', @@ -28,7 +28,31 @@ class ProfileCest { ]); } - // TODO: add cases for unauthenticated user - // TODO: add cases for authenticated as a service account user + public function getProfileAsServiceAccount(OauthSteps $I): void { + $accessToken = $I->getAccessTokenByClientCredentialsGrant(['internal_account_info']); + $I->amBearerAuthenticated($accessToken); + + $I->sendGet('/api/mojang/services/minecraft/profile'); + $I->canSeeResponseCodeIs(404); + $I->canSeeResponseContainsJson([ + 'path' => '/mojang/services/minecraft/profile', + 'errorType' => 'NOT_FOUND', + 'error' => 'NOT_FOUND', + 'errorMessage' => 'The server has not found anything matching the request URI', + 'developerMessage' => 'The server has not found anything matching the request URI', + ]); + } + + public function getProfileWithoutAuthentication(FunctionalTester $I): void { + $I->sendGet('/api/mojang/services/minecraft/profile'); + $I->canSeeResponseCodeIs(401); + $I->canSeeResponseContainsJson([ + 'path' => '/mojang/services/minecraft/profile', + 'errorType' => 'UnauthorizedOperationException', + 'error' => 'UnauthorizedOperationException', + 'errorMessage' => 'Unauthorized', + 'developerMessage' => 'Unauthorized', + ]); + } }