Реализованы методы для включения\отключения двухфакторной аутентификации

This commit is contained in:
ErickSkrauch 2017-01-21 02:28:26 +03:00
parent 3b9ef7ea70
commit be4c7908b2
4 changed files with 83 additions and 5 deletions

View File

@ -7,6 +7,9 @@ return [
'/accounts/change-email/submit-new-email' => 'accounts/change-email-submit-new-email', '/accounts/change-email/submit-new-email' => 'accounts/change-email-submit-new-email',
'/accounts/change-email/confirm-new-email' => 'accounts/change-email-confirm-new-email', '/accounts/change-email/confirm-new-email' => 'accounts/change-email-confirm-new-email',
'POST /two-factor-auth' => 'two-factor-auth/activate',
'DELETE /two-factor-auth' => 'two-factor-auth/disable',
'/oauth2/v1/<action>' => 'oauth/<action>', '/oauth2/v1/<action>' => 'oauth/<action>',
'/account/v1/info' => 'identity-info/index', '/account/v1/info' => 'identity-info/index',

View File

@ -34,4 +34,34 @@ class TwoFactorAuthController extends Controller {
return $model->getCredentials(); return $model->getCredentials();
} }
public function actionActivate() {
$account = Yii::$app->user->identity;
$model = new TwoFactorAuthForm($account, ['scenario' => TwoFactorAuthForm::SCENARIO_ACTIVATE]);
if (!$model->activate()) {
return [
'success' => false,
'errors' => $model->getFirstErrors(),
];
}
return [
'success' => true,
];
}
public function actionDisable() {
$account = Yii::$app->user->identity;
$model = new TwoFactorAuthForm($account, ['scenario' => TwoFactorAuthForm::SCENARIO_DISABLE]);
if (!$model->disable()) {
return [
'success' => false,
'errors' => $model->getFirstErrors(),
];
}
return [
'success' => true,
];
}
} }

View File

@ -18,7 +18,7 @@ use yii\base\ErrorException;
class TwoFactorAuthForm extends ApiForm { class TwoFactorAuthForm extends ApiForm {
const SCENARIO_ENABLE = 'enable'; const SCENARIO_ACTIVATE = 'enable';
const SCENARIO_DISABLE = 'disable'; const SCENARIO_DISABLE = 'disable';
public $token; public $token;
@ -36,11 +36,13 @@ class TwoFactorAuthForm extends ApiForm {
} }
public function rules() { public function rules() {
$on = [self::SCENARIO_ENABLE, self::SCENARIO_DISABLE]; $bothScenarios = [self::SCENARIO_ACTIVATE, self::SCENARIO_DISABLE];
return [ return [
['token', 'required', 'message' => E::OTP_TOKEN_REQUIRED, 'on' => $on], ['account', 'validateOtpDisabled', 'on' => self::SCENARIO_ACTIVATE],
['token', TotpValidator::class, 'account' => $this->account, 'window' => 30, 'on' => $on], ['account', 'validateOtpEnabled', 'on' => self::SCENARIO_DISABLE],
['password', PasswordRequiredValidator::class, 'account' => $this->account, 'on' => $on], ['token', 'required', 'message' => E::OTP_TOKEN_REQUIRED, 'on' => $bothScenarios],
['token', TotpValidator::class, 'account' => $this->account, 'window' => 30, 'on' => $bothScenarios],
['password', PasswordRequiredValidator::class, 'account' => $this->account, 'on' => $bothScenarios],
]; ];
} }
@ -58,6 +60,47 @@ class TwoFactorAuthForm extends ApiForm {
]; ];
} }
public function activate(): bool {
if (!$this->validate()) {
return false;
}
$account = $this->account;
$account->is_otp_enabled = true;
if (!$account->save()) {
throw new ErrorException('Cannot enable otp for account');
}
return true;
}
public function disable(): bool {
if (!$this->validate()) {
return false;
}
$account = $this->account;
$account->is_otp_enabled = false;
$account->otp_secret = null;
if (!$account->save()) {
throw new ErrorException('Cannot disable otp for account');
}
return true;
}
public function validateOtpDisabled($attribute) {
if ($this->account->is_otp_enabled) {
$this->addError($attribute, E::OTP_ALREADY_ENABLED);
}
}
public function validateOtpEnabled($attribute) {
if (!$this->account->is_otp_enabled) {
$this->addError($attribute, E::OTP_NOT_ENABLED);
}
}
public function getAccount(): Account { public function getAccount(): Account {
return $this->account; return $this->account;
} }

View File

@ -56,5 +56,7 @@ final class Error {
const OTP_TOKEN_REQUIRED = 'error.otp_token_required'; const OTP_TOKEN_REQUIRED = 'error.otp_token_required';
const OTP_TOKEN_INCORRECT = 'error.otp_token_incorrect'; const OTP_TOKEN_INCORRECT = 'error.otp_token_incorrect';
const OTP_ALREADY_ENABLED = 'error.otp_already_enabled';
const OTP_NOT_ENABLED = 'error.otp_not_enabled';
} }