diff --git a/api/config/routes.php b/api/config/routes.php index d0b9c34..d1ee9cf 100644 --- a/api/config/routes.php +++ b/api/config/routes.php @@ -1,3 +1,6 @@ 'accounts/change-email-initialize', + '/accounts/change-email/submit-new-email' => 'accounts/change-email-submit-new-email', + '/accounts/change-email/confirm-new-email' => 'accounts/change-email-confirm-new-email', ]; diff --git a/api/controllers/AccountsController.php b/api/controllers/AccountsController.php index 8e590e7..299d976 100644 --- a/api/controllers/AccountsController.php +++ b/api/controllers/AccountsController.php @@ -1,6 +1,9 @@ ['@'], ], [ - 'actions' => ['change-password', 'change-username'], + 'actions' => [ + 'change-password', + 'change-username', + 'change-email-initialize', + 'change-email-submit-new-email', + 'change-email-confirm-new-email', + ], 'allow' => true, 'roles' => ['@'], 'matchCallback' => function() { @@ -40,6 +49,9 @@ class AccountsController extends Controller { 'current' => ['GET'], 'change-password' => ['POST'], 'change-username' => ['POST'], + 'change-email-initialize' => ['POST'], + 'change-email-submit-new-email' => ['POST'], + 'change-email-confirm-new-email' => ['POST'], ]; } @@ -92,4 +104,57 @@ class AccountsController extends Controller { ]; } + public function actionChangeEmailInitialize() { + /** @var Account $account */ + $account = Yii::$app->user->identity; + $model = new InitStateForm($account); + if (!$model->sendCurrentEmailConfirmation()) { + return [ + 'success' => false, + 'errors' => $this->normalizeModelErrors($model->getErrors()), + ]; + } + + return [ + 'success' => true, + ]; + } + + public function actionChangeEmailSubmitNewEmail() { + /** @var Account $account */ + $account = Yii::$app->user->identity; + $model = new NewEmailForm($account); + $model->load(Yii::$app->request->post()); + if (!$model->sendNewEmailConfirmation()) { + return [ + 'success' => false, + 'errors' => $this->normalizeModelErrors($model->getErrors()), + ]; + } + + return [ + 'success' => true, + ]; + } + + public function actionChangeEmailConfirmNewEmail() { + /** @var Account $account */ + $account = Yii::$app->user->identity; + $model = new ConfirmNewEmailForm($account); + $model->load(Yii::$app->request->post()); + if (!$model->changeEmail()) { + return [ + 'success' => false, + 'errors' => $this->normalizeModelErrors($model->getErrors()), + ]; + } + + return [ + 'success' => true, + 'data' => [ + 'email' => $account->email, + ], + ]; + } + } diff --git a/api/models/profile/ChangeEmail/InitStateForm.php b/api/models/profile/ChangeEmail/InitStateForm.php index f956b2b..12e9200 100644 --- a/api/models/profile/ChangeEmail/InitStateForm.php +++ b/api/models/profile/ChangeEmail/InitStateForm.php @@ -28,7 +28,7 @@ class InitStateForm extends ApiForm { public function rules() { // TODO: поверить наличие уже отправленных подтверждений смены E-mail return [ - ['!email', 'validateAccountPasswordHashStrategy'], + ['!email', 'validateAccountPasswordHashStrategy', 'skipOnEmpty' => false], ]; } diff --git a/tests/codeception/api/_pages/AccountsRoute.php b/tests/codeception/api/_pages/AccountsRoute.php index 5fe1080..7dd1609 100644 --- a/tests/codeception/api/_pages/AccountsRoute.php +++ b/tests/codeception/api/_pages/AccountsRoute.php @@ -30,4 +30,9 @@ class AccountsRoute extends BasePage { ]); } + public function changeEmailInitialize() { + $this->route = ['accounts/change-email-initialize']; + $this->actor->sendPOST($this->getUrl()); + } + } diff --git a/tests/codeception/api/_support/FunctionalTester.php b/tests/codeception/api/_support/FunctionalTester.php index 3747e15..7ba0f4d 100644 --- a/tests/codeception/api/_support/FunctionalTester.php +++ b/tests/codeception/api/_support/FunctionalTester.php @@ -1,6 +1,8 @@ login('Admin', 'password_0'); - $I->canSeeResponseIsJson(); - $I->canSeeResponseJsonMatchesJsonPath('$.jwt'); - $jwt = $I->grabDataFromResponseByJsonPath('$.jwt')[0]; - $I->amBearerAuthenticated($jwt); + public function loggedInAsActiveAccount($login = null, $password = null) { + $route = new AuthenticationRoute($this); + if ($login === null) { + $route->login('Admin', 'password_0'); + } elseif ($login !== null && $password !== null) { + $route->login($login, $password); + } else { + throw new InvalidArgumentException('login and password should be presented both.'); + } + + $this->canSeeResponseIsJson(); + $this->canSeeResponseJsonMatchesJsonPath('$.jwt'); + $jwt = $this->grabDataFromResponseByJsonPath('$.jwt')[0]; + $this->amBearerAuthenticated($jwt); } public function notLoggedIn() { diff --git a/tests/codeception/api/functional/AccountsChangeEmailInitializeCest.php b/tests/codeception/api/functional/AccountsChangeEmailInitializeCest.php new file mode 100644 index 0000000..341086e --- /dev/null +++ b/tests/codeception/api/functional/AccountsChangeEmailInitializeCest.php @@ -0,0 +1,46 @@ +route = new AccountsRoute($I); + } + + public function testChangeEmailInitialize(FunctionalTester $I) { + $I->wantTo('send current email confirmation'); + $I->loggedInAsActiveAccount(); + + $this->route->changeEmailInitialize(); + $I->canSeeResponseCodeIs(200); + $I->canSeeResponseIsJson(); + $I->canSeeResponseContainsJson([ + 'success' => true, + ]); + } + + public function testChangeEmailWithOldPasswordStrategy(FunctionalTester $I) { + $I->wantTo('see, that account use old account password hash strategy'); + $I->loggedInAsActiveAccount('AccWithOldPassword', '12345678'); + + $this->route->changeEmailInitialize(); + $I->canSeeResponseCodeIs(200); + $I->canSeeResponseIsJson(); + $I->canSeeResponseContainsJson([ + 'success' => false, + 'errors' => [ + 'email' => 'error.old_hash_strategy', + ], + ]); + } + +}