diff --git a/api/controllers/AuthenticationController.php b/api/controllers/AuthenticationController.php index e9d336f..051e30c 100644 --- a/api/controllers/AuthenticationController.php +++ b/api/controllers/AuthenticationController.php @@ -3,6 +3,7 @@ namespace api\controllers; use api\models\authentication\ForgotPasswordForm; use api\models\authentication\LoginForm; +use api\models\authentication\LogoutForm; use api\models\authentication\RecoverPasswordForm; use api\models\authentication\RefreshTokenForm; use common\helpers\Error as E; @@ -26,6 +27,11 @@ class AuthenticationController extends Controller { 'allow' => true, 'roles' => ['?'], ], + [ + 'actions' => ['logout'], + 'allow' => true, + 'roles' => ['@'], + ], ], ], ]); @@ -34,6 +40,7 @@ class AuthenticationController extends Controller { public function verbs() { return [ 'login' => ['POST'], + 'logout' => ['POST'], 'forgot-password' => ['POST'], 'recover-password' => ['POST'], 'refresh-token' => ['POST'], @@ -61,6 +68,15 @@ class AuthenticationController extends Controller { ], $result->getAsResponse()); } + public function actionLogout() { + $form = new LogoutForm(); + $form->logout(); + + return [ + 'success' => true, + ]; + } + public function actionForgotPassword() { $model = new ForgotPasswordForm(); $model->load(Yii::$app->request->post()); diff --git a/api/models/authentication/LogoutForm.php b/api/models/authentication/LogoutForm.php new file mode 100644 index 0000000..64daf42 --- /dev/null +++ b/api/models/authentication/LogoutForm.php @@ -0,0 +1,20 @@ +user; + $session = $component->getActiveSession(); + if ($session === null) { + return true; + } + + $session->delete(); + + return true; + } + +} diff --git a/tests/codeception/api/_pages/AuthenticationRoute.php b/tests/codeception/api/_pages/AuthenticationRoute.php index 1b0d448..7ed0042 100644 --- a/tests/codeception/api/_pages/AuthenticationRoute.php +++ b/tests/codeception/api/_pages/AuthenticationRoute.php @@ -22,6 +22,11 @@ class AuthenticationRoute extends BasePage { $this->actor->sendPOST($this->getUrl(), $params); } + public function logout() { + $this->route = ['authentication/logout']; + $this->actor->sendPOST($this->getUrl()); + } + public function forgotPassword($login = '') { $this->route = ['authentication/forgot-password']; $this->actor->sendPOST($this->getUrl(), [ diff --git a/tests/codeception/api/functional/LogoutCest.php b/tests/codeception/api/functional/LogoutCest.php new file mode 100644 index 0000000..5acaa92 --- /dev/null +++ b/tests/codeception/api/functional/LogoutCest.php @@ -0,0 +1,18 @@ +loggedInAsActiveAccount(); + $route->logout(); + $I->canSeeResponseContainsJson([ + 'success' => true, + ]); + } + +} diff --git a/tests/codeception/api/unit/models/authentication/LogoutFormTest.php b/tests/codeception/api/unit/models/authentication/LogoutFormTest.php new file mode 100644 index 0000000..6cfbc92 --- /dev/null +++ b/tests/codeception/api/unit/models/authentication/LogoutFormTest.php @@ -0,0 +1,69 @@ +specify('No actions if active session is not exists', function () { + $userComp = $this + ->getMockBuilder(Component::class) + ->setConstructorArgs([$this->getComponentArgs()]) + ->setMethods(['getActiveSession']) + ->getMock(); + $userComp + ->expects($this->any()) + ->method('getActiveSession') + ->will($this->returnValue(null)); + + Yii::$app->set('user', $userComp); + + $model = new LogoutForm(); + expect($model->logout())->true(); + }); + + $this->specify('if active session is presented, then delete should be called', function () { + $session = $this + ->getMockBuilder(AccountSession::class) + ->setMethods(['delete']) + ->getMock(); + $session + ->expects($this->once()) + ->method('delete') + ->willReturn(true); + + $userComp = $this + ->getMockBuilder(Component::class) + ->setConstructorArgs([$this->getComponentArgs()]) + ->setMethods(['getActiveSession']) + ->getMock(); + $userComp + ->expects($this->any()) + ->method('getActiveSession') + ->will($this->returnValue($session)); + + Yii::$app->set('user', $userComp); + + $model = new LogoutForm(); + $model->logout(); + }); + } + + private function getComponentArgs() { + return [ + 'identityClass' => AccountIdentity::class, + 'enableSession' => false, + 'loginUrl' => null, + 'secret' => 'secret', + ]; + } + +}