add events + more wip classes

This commit is contained in:
Antonio Ramirez
2016-12-04 15:53:09 +01:00
parent 3e16d24048
commit bd06010018
21 changed files with 496 additions and 18 deletions

View File

@ -23,6 +23,7 @@ class Bootstrap implements BootstrapInterface
$classMap = $this->buildClassMap();
$this->initContainer($classMap);
$this->initTranslations($app);
$this->initMailServiceConfiguration($app, $app->getModule('user'));
if ($app instanceof WebApplication) {
$this->initUrlRoutes($app);
@ -44,9 +45,9 @@ class Bootstrap implements BootstrapInterface
$di = Yii::$container;
// email change strategy
$di->set('Da\User\Strategy\DefaultEmailChangeStrategy');
$di->set('Da\User\Strategy\InsecureEmailChangeStrategy');
$di->set('Da\User\Strategy\SecureEmailChangeStrategy');
$di->set(Strategy\DefaultEmailChangeStrategy::class);
$di->set(Strategy\InsecureEmailChangeStrategy::class);
$di->set(Strategy\SecureEmailChangeStrategy::class);
// models + active query classes
$modelClassMap = [];
@ -68,7 +69,7 @@ class Bootstrap implements BootstrapInterface
}
// helpers
$di->set('Da\User\Helper\AuthHelper');
$di->set(Helper\AuthHelper::class);
$di->setSingleton(ClassMapHelper::class, ClassMapHelper::class, [$modelClassMap]);
if (php_sapi_name() !== 'cli') {
@ -82,6 +83,20 @@ class Bootstrap implements BootstrapInterface
]
);
}
// services
$di->set(Service\UserCreateService::class);
// events
$di->set(Event\FormEvent::class);
$di->set(Event\ProfileEvent::class);
$di->set(Event\ResetPasswordEvent::class);
$di->set(Event\SocialNetworkAuthEvent::class);
$di->set(Event\SocialNetworkConnectEvent::class);
$di->set(Event\UserEvent::class);
// validators
$di->set(Validator\AjaxRequestModelValidator::class);
}
/**
@ -94,7 +109,7 @@ class Bootstrap implements BootstrapInterface
if (!isset($app->get('i18n')->translations['user*'])) {
$app->get('i18n')->translations['user*'] = [
'class' => PhpMessageSource::class,
'basePath' => __DIR__ . '/../i18n',
'basePath' => __DIR__ . '/resources/i18n',
'sourceLanguage' => 'en-US'
];
}
@ -123,6 +138,24 @@ class Bootstrap implements BootstrapInterface
$app->getUrlManager()->addRules([$rule], false);
}
/**
* Ensures required mail parameters needed for the mail service.
*
* @param Application $app
* @param Module $module
*/
protected function initMailServiceConfiguration(Application $app, Module $module)
{
$defaults = [
'welcomeMailSubject' => Yii::t('user', 'Welcome to {0}', $app->name),
'confirmationMailSubject' => Yii::t('user', 'Confirm account on {0}', $app->name),
'reconfirmationMailSubject' => Yii::t('user', 'Confirm email change on {0}', $app->name),
'recoveryMailSubject' => Yii::t('user', 'Complete password reset on {0}', $app->name)
];
$module->mailParams = array_merge($defaults, $module->mailParams);
}
/**
* Ensures the authCollection component is configured.
*

View File

@ -0,0 +1,10 @@
<?php
namespace Da\User\Contracts;
interface ValidatorInterface
{
/**
* @return bool
*/
public function validate();
}

View File

@ -0,0 +1,75 @@
<?php
namespace Da\User\Controller;
use Da\User\Event\UserEvent;
use Da\User\Filter\AccessRuleFilter;
use Da\User\Model\User;
use Da\User\Service\UserCreateService;
use Da\User\Traits\ContainerTrait;
use Da\User\Validator\AjaxRequestModelValidator;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\web\Controller;
use Yii;
class AdminController extends Controller
{
use ContainerTrait;
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
'confirm' => ['post'],
'block' => ['post'],
],
],
'access' => [
'class' => AccessControl::className(),
'ruleConfig' => [
'class' => AccessRuleFilter::className(),
],
'rules' => [
[
'allow' => true,
'roles' => ['admin'],
],
],
],
];
}
public function actionCreate()
{
/** @var User $user */
$user = $this->make(User::class, ['scenario' => 'create']);
/** @var UserEvent $event */
$event = $this->make(UserEvent::class, [$user]);
$this->make(AjaxRequestModelValidator::class, [$user])->validate();
$this->trigger(UserEvent::EVENT_BEFORE_CREATE, $event);
if($user->load(Yii::$app->request->post())) {
/** @var UserCreateService $userCreateService */
$userCreateService = $this->make(UserCreateService::class, [$user]);
$userCreateService->run();
$this->trigger(UserEvent::EVENT_AFTER_CREATE, $event);
return $this->redirect(['update', 'id' => $user->id]);
}
return $this->render('create', [
'user' => $user,
]);
}
}

View File

@ -0,0 +1,30 @@
<?php
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
{
protected $form;
public function __construct(Model $form, array $config = [])
{
$this->form = $form;
parent::__construct($config);
}
public function getForm()
{
return $this->form;
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace Da\User\Event;
use Da\User\Model\Profile;
use yii\base\Event;
class ProfileEvent extends Event
{
protected $profile;
public function __construct(Profile $profile, array $config = [])
{
$this->profile = $profile;
return parent::__construct($config);
}
public function getProfile()
{
return $this->profile;
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace Da\User\Event;
use Da\User\Form\RecoveryForm;
use Da\User\Model\Token;
use yii\base\Event;
class ResetPasswordEvent extends Event
{
protected $form;
protected $token;
public function __construct(RecoveryForm $form, Token $token, array $config = [])
{
$this->form = $form;
$this->token = $token;
parent::__construct($config);
}
public function getForm()
{
return $this->form;
}
public function getToken()
{
return $this->token;
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace Da\User\Event;
use Da\User\Model\SocialNetworkAccount;
use yii\authclient\ClientInterface;
use yii\base\Event;
class SocialNetworkAuthEvent extends Event
{
protected $client;
protected $account;
public function __construct(SocialNetworkAccount $account, ClientInterface $client, $config = [])
{
$this->account = $account;
$this->client = $client;
parent::__construct($config);
}
public function getClient()
{
return $this->client;
}
public function getAccount()
{
return $this->account;
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace Da\User\Event;
use Da\User\Model\SocialNetworkAccount;
use Da\User\Model\User;
use yii\base\Event;
class SocialNetworkConnectEvent extends Event
{
protected $user;
protected $account;
public function __construct(User $user, SocialNetworkAccount $account, $config = [])
{
$this->user = $user;
$this->account = $account;
parent::__construct($config);
}
public function getUser()
{
return $this->user;
}
public function getAccount()
{
return $this->account;
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace Da\User\Event;
use Da\User\Model\User;
use yii\base\Event;
class UserEvent extends Event
{
const EVENT_BEFORE_CREATE = 'beforeCreate';
const EVENT_AFTER_CREATE = 'afterCreate';
protected $user;
public function __construct(User $user, array $config = [])
{
$this->user = $user;
parent::__construct($config);
}
public function getUser()
{
return $this->user;
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace Da\User\Filter;
use Da\User\Model\User;
use yii\filters\AccessRule;
class AccessRuleFilter extends AccessRule
{
/**
* @inheritdoc
* */
protected function matchRole($user)
{
if (empty($this->roles)) {
return true;
}
foreach ($this->roles as $role) {
if ($role === '?') {
if ($user->getIsGuest()) {
return true;
}
} elseif ($role === '@') {
if (!$user->getIsGuest()) {
return true;
}
} elseif ($role === 'admin') {
/** @var User $identity */
$identity = $user->getIdentity();
if (!$user->getIsGuest() && $identity->getIsAdmin()) {
return true;
}
} elseif ($user->can($role)) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace Da\User\Form;
/**
*
* RecoveryForm.php
*
* Date: 4/12/16
* Time: 15:18
* @author Antonio Ramirez <hola@2amigos.us>
*/
class RecoveryForm
{
}

View File

@ -0,0 +1,15 @@
<?php
namespace Da\User\Model;
/**
*
* Profile.php
*
* Date: 4/12/16
* Time: 14:57
* @author Antonio Ramirez <hola@2amigos.us>
*/
class Profile
{
}

View File

@ -0,0 +1,15 @@
<?php
namespace Da\User\Model;
/**
*
* SocialNetworkAccount.php
*
* Date: 4/12/16
* Time: 14:56
* @author Antonio Ramirez <hola@2amigos.us>
*/
class SocialNetworkAccount
{
}

15
lib/User/Model/Token.php Normal file
View File

@ -0,0 +1,15 @@
<?php
namespace Da\User\Model;
/**
*
* Token.php
*
* Date: 4/12/16
* Time: 15:17
* @author Antonio Ramirez <hola@2amigos.us>
*/
class Token
{
}

View File

@ -60,6 +60,10 @@ class Module extends \yii\base\Module
* @var string the route prefix
*/
public $prefix = 'user';
/**
* @var array MailService configuration
*/
public $mailParams = [];
/**
* @var array the url rules (routes)

View File

@ -2,11 +2,51 @@
namespace Da\User\Service;
use Da\User\Contracts\ServiceInterface;
use yii\swiftmailer\Mailer;
use Yii;
class MailService implements ServiceInterface
{
protected $viewPath = '@Da/User/resources/views/mail';
protected $from;
protected $to;
protected $subject;
protected $view;
protected $params = [];
protected $mailer;
/**
* MailService constructor.
*
* @param string $from
* @param string $to
* @param string $subject
* @param string $view
* @param array $params
* @param Mailer $mailer
*/
public function __construct($from, $to, $subject, $view, array $params, Mailer $mailer)
{
$this->from = $from;
$this->to = $to;
$this->subject = $subject;
$this->view = $view;
$this->params = $params;
$this->mailer = $mailer;
$this->mailer->setViewPath($this->viewPath);
$this->mailer->getView()->theme = Yii::$app->view->theme;
}
/**
* @return bool
*/
public function run()
{
// TODO: Implement run() method.
return $this->mailer->compose(['html' => $this->view, 'text' => "text/{$this->view}"], $this->params)
->setFrom($this->from)
->setTo($this->to)
->setSubject($this->subject)
->send();
}
}

View File

@ -6,25 +6,20 @@ use Da\User\Helper\SecurityHelper;
use Da\User\Model\User;
use yii\base\InvalidCallException;
use Exception;
use yii\db\ActiveRecord;
use yii\log\Logger;
/**
*
* UserCreateService.php
*
* Date: 4/12/16
* Time: 2:55
* @author Antonio Ramirez <hola@2amigos.us>
*/
class UserCreateService implements ServiceInterface
{
protected $model;
protected $securityHelper;
protected $mailService;
protected $logger;
public function __construct(User $model, SecurityHelper $securityHelper, Logger $logger)
public function __construct(User $model, MailService $mailService, SecurityHelper $securityHelper, Logger $logger)
{
$this->model = $model;
$this->mailService = $mailService;
$this->securityHelper = $securityHelper;
$this->logger = $logger;
}
@ -48,7 +43,7 @@ class UserCreateService implements ServiceInterface
? $model->password
: $this->securityHelper->generatePassword(8);
// TODO: Trigger BEFORE CREATE EVENT
$model->trigger(ActiveRecord::EVENT_BEFORE_INSERT);
if (!$model->save()) {
$transaction->rollBack();
@ -56,8 +51,9 @@ class UserCreateService implements ServiceInterface
return false;
}
// TODO: Send welcome message
$model->trigger(ActiveRecord::EVENT_AFTER_INSERT);
$this->mailService->run();
$transaction->commit();
return true;

View File

@ -11,7 +11,7 @@ use Da\User\Contracts\StrategyInterface;
* Time: 16:21
* @author Antonio Ramirez <hola@2amigos.us>
*/
class InsecuredEmailChangeStrategy implements StrategyInterface
class InsecureEmailChangeStrategy implements StrategyInterface
{
}

View File

@ -19,6 +19,20 @@ trait ContainerTrait
return Yii::$container;
}
/**
* Gets a class from the container.
*
* @param string $class he class name or an alias name (e.g. `foo`) that was previously registered via [[set()]]
* or [[setSingleton()]].
* @param array $params
*
* @return object
*/
public function make($class, $params = [])
{
return $this->getDi()->get($class, $params);
}
/**
* @return \Da\User\Helper\AuthHelper
*/

View File

@ -0,0 +1,31 @@
<?php
namespace Da\User\Validator;
use Da\User\Contracts\ValidatorInterface;
use yii\base\Model;
use Yii;
use yii\bootstrap\ActiveForm;
use yii\web\Response;
class AjaxRequestModelValidator implements ValidatorInterface
{
protected $model;
public function __construct(Model $model)
{
$this->model = $model;
}
public function validate()
{
$request = Yii::$app->request;
if($request->getIsAjax() && !$request->getIsPjax()) {
if($this->model->load($request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
echo json_encode(ActiveForm::validate($this->model));
Yii::$app->end();
}
}
}
}

View File

@ -0,0 +1,46 @@
<?php
return [
'sourcePath' => __DIR__ . '/../User',
'messagePath' => __DIR__,
'languages' => [
'ca',
'da',
'de',
'de-DU',
'es',
'fa-IR',
'fi',
'fr',
'hr',
'hu',
'it',
'kz',
'lt',
'nl',
'pl',
'pt-BR',
'pt-PT',
'ro',
'ru',
'th',
'tr_TR',
'uk',
'vi',
'zh-CN',
],
'translator' => 'Yii::t',
'sort' => false,
'overwrite' => true,
'removeUnused' => false,
'only' => ['*.php'],
'except' => [
'.svn',
'.git',
'.gitignore',
'.gitkeep',
'.hgignore',
'.hgkeep'
],
'format' => 'php',
];