starting with password recovery procedures

This commit is contained in:
Antonio Ramirez
2016-12-06 14:31:11 +01:00
parent c5279eb13c
commit ea68cb3d84
11 changed files with 243 additions and 40 deletions

View File

@ -3,7 +3,6 @@
namespace Da\User;
use Da\User\Helper\ClassMapHelper;
use Da\User\Model\Profile;
use Da\User\Validator\TimeZoneValidator;
use Yii;
use yii\authclient\Collection;
@ -22,8 +21,8 @@ class Bootstrap implements BootstrapInterface
public function bootstrap($app)
{
if ($app->hasModule('user') && $app->getModule('user') instanceof Module) {
$classMap = $this->buildClassMap();
$this->initContainer($classMap);
$map = $this->buildClassMap($app->getModule('user')->classMap);
$this->initContainer($map);
$this->initTranslations($app);
$this->initMailServiceConfiguration($app, $app->getModule('user'));
@ -184,22 +183,25 @@ class Bootstrap implements BootstrapInterface
}
/**
* Builds class map according to use configuration
* Builds class map according to user configuration
*
* @param array $userClassMap user configuration on the module
*
* @return array
*/
protected function buildClassMap()
protected function buildClassMap(array $userClassMap)
{
$map = [];
$defaults = [
// --- models
'User' => 'Da\User\Model\User',
'Account' => 'Da\User\Model\Account',
'Profile' => 'Da\User\Model\Profile',
'Token' => 'Da\User\Model\Token',
// ---
// --- search
'UserSearch' => 'Da\User\Search\UserSearch',
// ---
// --- forms
'RegistrationForm' => 'Da\User\Form\RegistrationForm',
'ResendForm' => 'Da\User\Form\ResendForm',
'LoginForm' => 'Da\User\Form\LoginForm',
@ -226,7 +228,9 @@ class Bootstrap implements BootstrapInterface
]
];
foreach ($defaults as $name => $definition) {
$mapping = array_merge($defaults, $userClassMap);
foreach ($mapping as $name => $definition) {
$map[$this->getRoute($routes, $name) . "\\$name"] = $definition;
}

View File

@ -54,7 +54,7 @@ class AdminController extends Controller
*/
public function beforeAction($action)
{
if (in_array($action->id, ['index', 'update', 'update-profile', 'info', 'assingments'])) {
if (in_array($action->id, ['index', 'update', 'update-profile', 'info', 'assignments'])) {
Url::remember('', 'actions-redirect');
}
@ -120,11 +120,13 @@ class AdminController extends Controller
$mailService = MailFactory::makeWelcomeMailerService($user);
$this->make(UserCreateService::class, [$user, $mailService])->run();
if ($this->make(UserCreateService::class, [$user, $mailService])->run()) {
$this->trigger(UserEvent::EVENT_AFTER_CREATE, $event);
Yii::$app->getSession()->setFlash('success', Yii::t('user', 'User has been created'));
$this->trigger(UserEvent::EVENT_AFTER_CREATE, $event);
return $this->redirect(['update', 'id' => $user->id]);
return $this->redirect(['update', 'id' => $user->id]);
}
}
return $this->render('create', ['user' => $user]);

View File

@ -0,0 +1,96 @@
<?php
namespace Da\User\Controller;
use Da\User\Event\FormEvent;
use Da\User\Factory\MailFactory;
use Da\User\Form\RecoveryForm;
use Da\User\Model\Token;
use Da\User\Query\TokenQuery;
use Da\User\Query\UserQuery;
use Da\User\Service\PasswordRecoveryService;
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 RecoveryController extends Controller
{
use ModuleTrait;
use ContainerTrait;
protected $userQuery;
protected $tokenQuery;
/**
* RecoveryController constructor.
*
* @param string $id
* @param Module $module
* @param UserQuery $userQuery
* @param TokenQuery $tokenQuery
* @param array $config
*/
public function __construct($id, Module $module, UserQuery $userQuery, TokenQuery $tokenQuery, array $config)
{
$this->userQuery = $userQuery;
$this->tokenQuery = $tokenQuery;
parent::__construct($id, $module, $config);
}
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'actions' => ['request', 'reset'],
'roles' => ['?']
],
],
],
];
}
public function actionRequest()
{
if (!$this->getModule()->allowPasswordRecovery) {
throw new NotFoundHttpException();
}
/** @var RecoveryForm $form */
$form = $this->make(RecoveryForm::class, ['scenario' => RecoveryForm::SCENARIO_REQUEST]);
$event = $this->make(FormEvent::class, [$form]);
$this->make(AjaxRequestModelValidator::class, $form)->validate();
$this->trigger(FormEvent::EVENT_BEFORE_REQUEST, $event);
if ($form->load(Yii::$app->request->post())) {
$mailService = MailFactory::makeRecoveryMailerService($form->email);
if ($this->make(PasswordRecoveryService::class, [$form->email, $mailService])->run()) {
$this->trigger(FormEvent::EVENT_AFTER_REQUEST, $event);
return $this->render(
'message',
[
'title' => Yii::t('user', 'Recovery message sent'),
'module' => $this->getModule(),
]
);
}
}
return $this->render('request', ['model' => $form,]);
}
}

View File

@ -4,16 +4,11 @@ namespace Da\User\Event;
use yii\base\Event;
use yii\base\Model;
/**
*
* FormEvent.php
*
* Date: 4/12/16
* Time: 15:11
* @author Antonio Ramirez <hola@2amigos.us>
*/
class FormEvent extends Event
{
const EVENT_BEFORE_REQUEST = 'beforeRequest';
const EVENT_AFTER_REQUEST = 'afterRequest';
protected $form;
public function __construct(Model $form, array $config = [])

View File

@ -8,6 +8,11 @@ use yii\base\Event;
class ResetPasswordEvent extends Event
{
const EVENT_BEFORE_TOKEN_VALIDATE = 'beforeTokenValidate';
const EVENT_AFTER_TOKEN_VALIDATE = 'afterTokenValidate';
const EVENT_BEFORE_RESET = 'beforeReset';
const EVENT_AFTER_RESET = 'afterReset';
protected $form;
protected $token;

View File

@ -1,14 +1,19 @@
<?php
namespace Da\User\Factory;
use Da\User\Model\Token;
use Da\User\Model\User;
use Da\User\Module;
use Da\User\Service\MailService;
use Da\User\Traits\ModuleTrait;
use Yii;
class MailFactory
{
/**
* @param User $user
*
* @return MailService
*/
public static function makeWelcomeMailerService(User $user)
{
/** @var Module $module */
@ -26,6 +31,21 @@ class MailFactory
return static::makeMailerService($from, $to, $subject, 'welcome', $params);
}
/**
* @param string $email
* @param Token $token
*
* @return MailService
*/
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'];
return static::makeMailerService($from, $to, $subject, 'recovery');
}
/**
* Builds a MailerService
*

View File

@ -67,6 +67,10 @@ class Module extends \yii\base\Module
* compute the hash doubles for every increment by one of $cost.
*/
public $blowfishCost = 10;
/**
* @var array the class map. How the container should load specific classes.
*/
public $classMap = [];
/**
* @var array the url rules (routes)

View File

@ -38,6 +38,19 @@ class MailService implements ServiceInterface
$this->mailer->getView()->theme = Yii::$app->view->theme;
}
/**
* @param $name
* @param $value
*
* @return $this
*/
public function setViewParam($name, $value)
{
$this->params[$name] = $value;
return $this;
}
/**
* @return bool
*/

View File

@ -1,15 +1,63 @@
<?php
namespace Da\User\Service;
/**
*
* PasswordRecoveryService.php
*
* Date: 5/12/16
* Time: 14:18
* @author Antonio Ramirez <hola@2amigos.us>
*/
class PasswordRecoveryService
use Da\User\Contracts\ServiceInterface;
use Da\User\Model\Token;
use Da\User\Model\User;
use Da\User\Query\UserQuery;
use Exception;
use Yii;
use yii\log\Logger;
class PasswordRecoveryService implements ServiceInterface
{
protected $query;
protected $email;
protected $mailService;
protected $securityHelper;
protected $logger;
public function __construct($email, MailService $mailService, UserQuery $query, Logger $logger)
{
$this->email = $email;
$this->mailService = $mailService;
$this->query = $query;
$this->logger = $logger;
}
public function run()
{
try {
/** @var User $user */
$user = $this->query->whereEmail($this->email)->one();
/** @var Token $token */
$token = Yii::createObject(
[
'class' => Token::class,
'user_id' => $user->id,
'type' => Token::TYPE_RECOVERY
]
);
if (!$token->save(false)) {
return false;
}
$this->mailService->setViewParam('user', $user);
$this->mailService->setViewParam('token', $token);
if (!$this->mailService->run()) {
return false;
}
return true;
} catch (Exception $e) {
$this->logger->log($e->getMessage(), Logger::LEVEL_ERROR);
return false;
}
}
}

View File

@ -1,15 +1,31 @@
<?php
namespace Da\User\Service;
/**
*
* ResetPasswordService.php
*
* Date: 5/12/16
* Time: 14:17
* @author Antonio Ramirez <hola@2amigos.us>
*/
class ResetPasswordService
use Da\User\Contracts\ServiceInterface;
use Da\User\Helper\SecurityHelper;
use Da\User\Model\User;
class ResetPasswordService implements ServiceInterface
{
protected $password;
protected $model;
protected $securityHelper;
public function __construct($password, User $model, SecurityHelper $securityHelper)
{
$this->password;
$this->model = $model;
$this->securityHelper = $securityHelper;
}
public function run()
{
return (bool)$this->model->updateAttributes(
[
'password_hash' => $this->securityHelper->generatePasswordHash($this->password)
]
);
}
}

View File

@ -60,7 +60,7 @@ class UserCreateService implements ServiceInterface
} catch (Exception $e) {
$transaction->rollBack();
$this->logger->log($e->getMessage(), Logger::LEVEL_WARNING);
$this->logger->log($e->getMessage(), Logger::LEVEL_ERROR);
return false;
}