add resend functionality

This commit is contained in:
Antonio Ramirez
2016-12-09 01:39:55 +01:00
parent 6f9cc5188e
commit c3aad1b47d
11 changed files with 310 additions and 53 deletions

View File

@ -12,7 +12,6 @@ use Da\User\Service\UserBlockService;
use Da\User\Service\UserConfirmationService;
use Da\User\Service\UserCreateService;
use Da\User\Traits\ContainerTrait;
use Da\User\Traits\ModuleTrait;
use Da\User\Validator\AjaxRequestModelValidator;
use Yii;
use yii\base\Module;
@ -25,7 +24,6 @@ use yii\web\Controller;
class AdminController extends Controller
{
use ModuleTrait;
use ContainerTrait;
/**
@ -165,6 +163,7 @@ class AdminController extends Controller
/** @var UserEvent $event */
$event = $this->make(UserEvent::class, [$user]);
$this->make(AjaxRequestModelValidator::class, [$user])->validate();
$this->trigger(UserEvent::EVENT_BEFORE_PROFILE_UPDATE, $event);
if ($profile->load(Yii::$app->request->post()) && $profile->save()) {
@ -215,6 +214,7 @@ class AdminController extends Controller
$user = $this->userQuery->where(['id' => $id])->one();
/** @var UserEvent $event */
$event = $this->make(UserEvent::class, [$user]);
$this->trigger(UserEvent::EVENT_BEFORE_CONFIRMATION, $event);
if ($this->make(UserConfirmationService::class, [$user])->run()) {
Yii::$app->getSession()->setFlash('success', Yii::t('user', 'User has been confirmed'));

View File

@ -11,17 +11,15 @@ use Da\User\Query\UserQuery;
use Da\User\Service\PasswordRecoveryService;
use Da\User\Service\ResetPasswordService;
use Da\User\Traits\ContainerTrait;
use Da\User\Traits\ModuleTrait;
use Da\User\Validator\AjaxRequestModelValidator;
use Yii;
use yii\base\Module;
use Da\User\Module;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
class RecoveryController extends Controller
{
use ModuleTrait;
use ContainerTrait;
protected $userQuery;
@ -70,7 +68,8 @@ class RecoveryController extends Controller
*/
public function actionRequest()
{
if (!$this->getModule()->allowPasswordRecovery) {
if (!$this->module->allowPasswordRecovery) {
throw new NotFoundHttpException();
}
@ -93,7 +92,7 @@ class RecoveryController extends Controller
'message',
[
'title' => Yii::t('user', 'Recovery message sent'),
'module' => $this->getModule(),
'module' => $this->module,
]
);
}
@ -113,7 +112,7 @@ class RecoveryController extends Controller
*/
public function actionReset($id, $code)
{
if (!$this->getModule()->allowPasswordRecovery) {
if (!$this->module->allowPasswordRecovery) {
throw new NotFoundHttpException();
}
/** @var Token $token */
@ -133,7 +132,7 @@ class RecoveryController extends Controller
'message',
[
'title' => Yii::t('user', 'Invalid or expired link'),
'module' => $this->getModule(),
'module' => $this->module,
]
);
}
@ -152,7 +151,7 @@ class RecoveryController extends Controller
'message',
[
'title' => Yii::t('user', 'Password has been changed'),
'module' => $this->getModule(),
'module' => $this->module,
]
);
}

View File

@ -0,0 +1,181 @@
<?php
namespace Da\User\Controller;
use Da\User\Event\FormEvent;
use Da\User\Event\SocialNetworkConnectEvent;
use Da\User\Event\UserEvent;
use Da\User\Factory\MailFactory;
use Da\User\Form\ResendForm;
use Da\User\Model\SocialNetworkAccount;
use Da\User\Model\User;
use Da\User\Query\SocialNetworkAccountQuery;
use Da\User\Query\UserQuery;
use Da\User\Service\ResendConfirmationService;
use Da\User\Service\UserCreateService;
use Da\User\Traits\ContainerTrait;
use Da\User\Traits\ModuleTrait;
use Da\User\Validator\AjaxRequestModelValidator;
use Yii;
use yii\base\Module;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
class RegistrationController extends Controller
{
use ModuleTrait;
use ContainerTrait;
protected $userQuery;
protected $socialNetworkAccountQuery;
/**
* RegistrationController constructor.
*
* @param string $id
* @param Module $module
* @param UserQuery $userQuery
* @param SocialNetworkAccountQuery $socialNetworkAccountQuery
* @param array $config
*/
public function __construct(
$id,
Module $module,
UserQuery $userQuery,
SocialNetworkAccountQuery $socialNetworkAccountQuery,
array $config
) {
$this->userQuery = $userQuery;
$this->socialNetworkAccountQuery = $socialNetworkAccountQuery;
parent::__construct($id, $module, $config);
}
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'actions' => ['register', 'connect'],
'roles' => ['?']
],
[
'allow' => true,
'actions' => ['confirm', 'resend'],
'roles' => ['?', '@']
],
],
],
];
}
public function actionConnect($code)
{
/** @var SocialNetworkAccount $account */
$account = $this->socialNetworkAccountQuery->whereCode($code)->one();
if ($account === null || $account->getIsConnected()) {
throw new NotFoundHttpException();
}
/** @var User $user */
$user = $this->make(
User::class,
['scenario' => 'connect', 'username' => $account->username, 'email' => $account->email]
);
$event = $this->make(SocialNetworkConnectEvent::class, [$user, $account]);
$this->make(AjaxRequestModelValidator::class, [$user])->validate();
$this->trigger(SocialNetworkConnectEvent::EVENT_BEFORE_CONNECT, $event);
if ($user->load(Yii::$app->request->post())) {
$mailService = MailFactory::makeWelcomeMailerService($user);
if ($this->make(UserCreateService::class, [$user, $mailService])->run()) {
$account->connect($user);
$this->trigger(SocialNetworkConnectEvent::EVENT_AFTER_CONNECT, $event);
Yii::$app->user->login($user, $this->module->rememberLoginLifespan);
return $this->goBack();
}
}
return $this->render(
'connect',
[
'model' => $user,
'account' => $account,
]
);
}
public function actionConfirm($id, $code)
{
$user = $this->userQuery->whereId($id)->one();
if ($user === null || $this->module->enableEmailConfirmation === false) {
throw new NotFoundHttpException();
}
/** @var UserEvent $event */
$event = $this->make(UserEvent::class, [$user]);
$this->trigger(UserEvent::EVENT_BEFORE_CONFIRMATION, $event);
// TODO ATTEMPT CONFIRMATION
$this->trigger(UserEvent::EVENT_AFTER_CONFIRMATION, $event);
return $this->render(
'message',
[
'title' => Yii::t('user', 'Account confirmation'),
'module' => $this->module,
]
);
}
public function actionResend()
{
if ($this->module->enableEmailConfirmation === false) {
throw new NotFoundHttpException();
}
/** @var ResendForm $form */
$form = $this->make(ResendForm::class);
$event = $this->make(FormEvent::class, [$form]);
$this->make(AjaxRequestModelValidator::class, [$form])->validate();
$this->trigger(FormEvent::EVENT_BEFORE_RESEND, $event);
if ($form->load(Yii::$app->request->post()) && $form->validate()) {
/** @var User $user */
$user = $this->userQuery->whereEmail($form->email)->one();
$mailService = MailFactory::makeConfirmationMailerService($user);
if ($this->make(ResendConfirmationService::class, [$user, $mailService])->run()) {
$this->trigger(FormEvent::EVENT_AFTER_RESEND, $event);
Yii::$app->session->setFlash(
'info',
Yii::t(
'user',
'A message has been sent to your email address. It contains a confirmation link that you must
click to complete registration.'
)
);
} else {
Yii::$app->session->setFlash(
'danger',
Yii::t(
'user',
'We couldn\'t re-send the mail to confirm your address. Please, verify is the correct email.'
)
);
}
}
}
}

View File

@ -8,6 +8,8 @@ class FormEvent extends Event
{
const EVENT_BEFORE_REQUEST = 'beforeRequest';
const EVENT_AFTER_REQUEST = 'afterRequest';
const EVENT_BEFORE_RESEND = 'beforeResend';
const EVENT_AFTER_RESEND = 'afterResend';
protected $form;

View File

@ -8,6 +8,9 @@ use yii\base\Event;
class SocialNetworkConnectEvent extends Event
{
const EVENT_BEFORE_CONNECT = 'beforeConnect';
const EVENT_AFTER_CONNECT = 'afterConnect';
protected $user;
protected $account;

View File

@ -37,15 +37,36 @@ class MailFactory
*
* @return MailService
*/
public static function makeRecoveryMailerService($email, Token $token = null) {
public static function makeRecoveryMailerService($email, Token $token = null)
{
/** @var Module $module */
$module = Yii::$app->getModule('user');
$to = $email;
$from = $module->mailParams['fromEmail'];
$subject = $module->mailParams['recoveryMailSubject'];
$params = [
'user' => $token && $token->user ? $token->user : null,
'token' => $token
];
return static::makeMailerService($from, $to, $subject, 'recovery');
return static::makeMailerService($from, $to, $subject, 'recovery', $params);
}
public static function makeConfirmationMailerService(User $user, Token $token = null)
{
/** @var Module $module */
$module = Yii::$app->getModule('user');
$to = $user->email;
$from = $module->mailParams['fromEmail'];
$subject = $module->mailParams['confirmationMailSubject'];
$params = [
'user' => $token && $token->user ? $token->user : null,
'token' => $token
];
return static::makeMailerService($from, $to, $subject, 'recovery', $params);
}
/**
* Builds a MailerService
*

View File

@ -0,0 +1,33 @@
<?php
namespace Da\User\Factory;
use Da\User\Model\Token;
use Da\User\Model\User;
use Da\User\Traits\ContainerTrait;
use Yii;
class TokenFactory
{
/**
* @param $userId
*
* @return Token
*/
public static function makeConfirmationToken($userId)
{
$token = self::make(Token::class, ['user_id' => $userId, 'type' => Token::TYPE_CONFIRMATION]);
$token->save(false);
return $token;
}
protected static function make($class, $params = [])
{
return Yii::$container->get($class, $params);
}
}

View File

@ -1,52 +1,28 @@
<?php
namespace Da\User\Form;
/*
* This file is part of the Dektrium project.
*
* (c) Dektrium project <http://github.com/dektrium/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace dektrium\user\models;
use dektrium\user\Finder;
use dektrium\user\Mailer;
use Da\User\Query\UserQuery;
use Yii;
use yii\base\Model;
/**
* ResendForm gets user email address and if user with given email is registered it sends new confirmation message
* to him in case he did not validate his email.
*
* @author Dmitry Erofeev <dmeroff@gmail.com>
*/
class ResendForm extends Model
{
/**
* @var string
*/
public $email;
/**
* @var Mailer
* @var UserQuery
*/
protected $mailer;
protected $userQuery;
/**
* @var Finder
*/
protected $finder;
/**
* @param Mailer $mailer
* @param Finder $finder
* @param UserQuery $userQuery
* @param array $config
*/
public function __construct(Mailer $mailer, Finder $finder, $config = [])
public function __construct(UserQuery $userQuery, $config = [])
{
$this->mailer = $mailer;
$this->finder = $finder;
$this->userQuery = $userQuery;
parent::__construct($config);
}
@ -67,18 +43,10 @@ class ResendForm extends Model
public function attributeLabels()
{
return [
'email' => \Yii::t('user', 'Email'),
'email' => Yii::t('user', 'Email'),
];
}
/**
* @inheritdoc
*/
public function formName()
{
return 'resend-form';
}
/**
* Creates new confirmation token and sends it to the user.
*
@ -90,6 +58,8 @@ class ResendForm extends Model
return false;
}
$user = $this->userQuery->whereEmail($this->email)->one();
$user = $this->finder->findUserByEmail($this->email);
if ($user instanceof User && !$user->isConfirmed) {

View File

@ -15,4 +15,9 @@ class SocialNetworkAccountQuery extends ActiveQuery
]
);
}
public function whereCode($code)
{
return $this->andWhere(['code' => md5($code)]);
}
}

View File

@ -22,4 +22,9 @@ class UserQuery extends ActiveQuery
{
return $this->andWhere(['username' => $username]);
}
public function whereId($id)
{
return $this->andWhere(['id' => $id]);
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace Da\User\Service;
use Da\User\Contracts\ServiceInterface;
use Da\User\Factory\TokenFactory;
use Da\User\Helper\SecurityHelper;
use Da\User\Model\Token;
use Da\User\Model\User;
use Da\User\Query\UserQuery;
use yii\log\Logger;
class ResendConfirmationService implements ServiceInterface
{
protected $model;
protected $mailService;
protected $logger;
public function __construct(User $model, MailService $mailService, Logger $logger)
{
$this->model = $model;
$this->mailService = $mailService;
$this->logger = $logger;
}
public function run()
{
if($this->model && !$this->model->getIsConfirmed()) {
$token = TokenFactory::makeConfirmationToken($this->model->id);
$this->mailService->setViewParam('token', $token);
return $this->mailService->run();
}
return false;
}
}