* * For the full copyright and license information, please view * the LICENSE file that was distributed with this source code. */ namespace Da\User\Controller; use Da\User\Contracts\AuthClientInterface; use Da\User\Event\FormEvent; use Da\User\Event\UserEvent; use Da\User\Form\LoginForm; use Da\User\Query\SocialNetworkAccountQuery; use Da\User\Service\SocialNetworkAccountConnectService; use Da\User\Service\SocialNetworkAuthenticateService; use Da\User\Traits\ContainerAwareTrait; use Yii; use yii\authclient\AuthAction; use yii\base\Module; use yii\filters\AccessControl; use yii\filters\VerbFilter; use yii\web\Controller; use yii\web\Response; use yii\widgets\ActiveForm; class SecurityController extends Controller { use ContainerAwareTrait; protected $socialNetworkAccountQuery; /** * SecurityController constructor. * * @param string $id * @param Module $module * @param SocialNetworkAccountQuery $socialNetworkAccountQuery * @param array $config */ public function __construct( $id, Module $module, SocialNetworkAccountQuery $socialNetworkAccountQuery, array $config = [] ) { $this->socialNetworkAccountQuery = $socialNetworkAccountQuery; parent::__construct($id, $module, $config); } /** * {@inheritdoc} */ public function behaviors() { return [ 'access' => [ 'class' => AccessControl::className(), 'rules' => [ [ 'allow' => true, 'actions' => ['login', 'confirm', 'auth', 'blocked'], 'roles' => ['?'], ], [ 'allow' => true, 'actions' => ['login', 'auth', 'logout'], 'roles' => ['@'], ], ], ], 'verbs' => [ 'class' => VerbFilter::className(), 'actions' => [ 'logout' => ['post'], ], ], ]; } /** * {@inheritdoc} */ public function actions() { return [ 'auth' => [ 'class' => AuthAction::className(), // if user is not logged in, will try to log him in, otherwise // will try to connect social account to user. 'successCallback' => Yii::$app->user->isGuest ? [$this, 'authenticate'] : [$this, 'connect'], ], ]; } /** * Controller action responsible for handling login page and actions. * * @return array|string|Response */ public function actionLogin() { if (!Yii::$app->user->getIsGuest()) { return $this->goHome(); } /** @var LoginForm $form */ $form = $this->make(LoginForm::class); /** @var FormEvent $event */ $event = $this->make(FormEvent::class, [$form]); if (Yii::$app->request->isAjax && $form->load(Yii::$app->request->post())) { Yii::$app->response->format = Response::FORMAT_JSON; return ActiveForm::validate($form); } if ($form->load(Yii::$app->request->post())) { if ($this->module->enableTwoFactorAuthentication && $form->validate()) { if ($form->getUser()->auth_tf_enabled) { Yii::$app->session->set('credentials', ['login' => $form->login, 'pwd' => $form->password]); return $this->redirect(['confirm']); } } $this->trigger(FormEvent::EVENT_BEFORE_LOGIN, $event); if ($form->login()) { $form->getUser()->updateAttributes(['last_login_at' => time()]); $this->trigger(FormEvent::EVENT_AFTER_LOGIN, $event); return $this->goBack(); } } return $this->render( 'login', [ 'model' => $form, 'module' => $this->module, ] ); } public function actionConfirm() { if (!Yii::$app->user->getIsGuest()) { return $this->goHome(); } if (!Yii::$app->session->has('credentials')) { return $this->redirect(['login']); } $credentials = Yii::$app->session->get('credentials'); /** @var LoginForm $form */ $form = $this->make(LoginForm::class); $form->login = $credentials['login']; $form->password = $credentials['pwd']; $form->setScenario('2fa'); /** @var FormEvent $event */ $event = $this->make(FormEvent::class, [$form]); if (Yii::$app->request->isAjax && $form->load(Yii::$app->request->post())) { Yii::$app->response->format = Response::FORMAT_JSON; return ActiveForm::validate($form); } if ($form->load(Yii::$app->request->post())) { $this->trigger(FormEvent::EVENT_BEFORE_LOGIN, $event); if ($form->login()) { Yii::$app->session->set('credentials', null); $form->getUser()->updateAttributes(['last_login_at' => time()]); $this->trigger(FormEvent::EVENT_AFTER_LOGIN, $event); return $this->goBack(); } } return $this->render( 'confirm', [ 'model' => $form, 'module' => $this->module, ] ); } public function actionLogout() { $event = $this->make(UserEvent::class, [Yii::$app->getUser()->getIdentity()]); $this->trigger(UserEvent::EVENT_BEFORE_LOGOUT, $event); if (Yii::$app->getUser()->logout()) { $this->trigger(UserEvent::EVENT_AFTER_LOGOUT, $event); } return $this->goHome(); } public function authenticate(AuthClientInterface $client) { $this->make(SocialNetworkAuthenticateService::class, [$this, $this->action, $client])->run(); } public function connect(AuthClientInterface $client) { if (Yii::$app->user->isGuest) { Yii::$app->session->setFlash('danger', Yii::t('usuario', 'Something went wrong')); return; } $this->make(SocialNetworkAccountConnectService::class, [$this, $client])->run(); } }