Meged from upstream master
This commit is contained in:
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,11 +1,22 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
## 1.1.2 - Work in progress
|
## 1.1.4 - Work in progress
|
||||||
|
- Enh: Check enableEmailConfirmation on registration (faenir)
|
||||||
|
- Fix #154: Fix DateTime constructor with Unix timestamps (tonydspaniard)
|
||||||
|
|
||||||
|
## 1.1.2-3 - February 9, 2018
|
||||||
|
- Bug: Bugfix for Model events UserEvent::EVENT_BEFORE_CONFIRMATION and UserEvent::EVENT_AFTER_CONFIRMATION (ajmedway)
|
||||||
|
- Bug: Bugfix for Model events UserEvent::EVENT_BEFORE_CREATE and UserEvent::EVENT_AFTER_CREATE (ajmedway)
|
||||||
- Enh #137: Added the ability to make `enableAutologin` configurable (pappfer)
|
- Enh #137: Added the ability to make `enableAutologin` configurable (pappfer)
|
||||||
- Enh #135: Added Estonian translation (tonisormisson)
|
- Enh #135: Added Estonian translation (tonisormisson)
|
||||||
- Bug #133: Fix user search returning no results in admin page (phiurs)
|
- Bug #133: Fix user search returning no results in admin page (phiurs)
|
||||||
- Bug #125: Fix validation in non-ajax requests (faenir)
|
- Bug #125: Fix validation in non-ajax requests (faenir)
|
||||||
- Bug #122: Fix wrong email message for email address change (liviuk2)
|
- Bug #122: Fix wrong email message for email address change (liviuk2)
|
||||||
|
- Bug #102: Implemented password expiration feature (maxxer)
|
||||||
|
- Enh #143: Introduced "conflict" configuration in composer.json (maxxer)
|
||||||
|
- Enh #145: Allowed the `+` sign in username (maxxer)
|
||||||
|
- Bug #9: Documentation about migration from Dektrium tools (maxxer)
|
||||||
|
- Bug #110: Honor `enableFlashMessages` in `PasswordRecoveryService` (maxxer)
|
||||||
|
|
||||||
## 1.1.1 - November 27, 2017
|
## 1.1.1 - November 27, 2017
|
||||||
- Bug #115: Convert client_id to string because pgsql fail with type convertion (Dezinger)
|
- Bug #115: Convert client_id to string because pgsql fail with type convertion (Dezinger)
|
||||||
|
|||||||
@ -89,6 +89,10 @@
|
|||||||
"pattern-skip-version": "(-build|-patch)"
|
"pattern-skip-version": "(-build|-patch)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"conflict": {
|
||||||
|
"dektrium/yii2-rbac": "*",
|
||||||
|
"dektrium/yii2-user": "*"
|
||||||
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
"bootstrap": "Da\\User\\Bootstrap"
|
"bootstrap": "Da\\User\\Bootstrap"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -110,10 +110,27 @@ Once we have it installed, we have to configure it on your `config.php` file.
|
|||||||
'modules' => [
|
'modules' => [
|
||||||
'user' => [
|
'user' => [
|
||||||
'class' => Da\User\Module::class,
|
'class' => Da\User\Module::class,
|
||||||
|
// ...other configs from here: [Configuration Options](installation/configuration-options.md), e.g.
|
||||||
|
// 'generatePasswords' => true,
|
||||||
|
// 'switchIdentitySessionKey' => 'myown_usuario_admin_user_key',
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
NOTE: If you are using the Yii2 Basic Template, make sure you remove this (default user model config) from your `config.php`,
|
||||||
|
i.e. `config/web.php` file:
|
||||||
|
|
||||||
|
```php
|
||||||
|
'components' => [
|
||||||
|
'user' => [
|
||||||
|
'identityClass' => 'app\models\User',
|
||||||
|
'enableAutoLogin' => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
This will ensure the proper functionality of login/guest user detection etc.
|
||||||
|
|
||||||
Configuration may differ from template to template, the following are some guidelines for sidekit app template and
|
Configuration may differ from template to template, the following are some guidelines for sidekit app template and
|
||||||
the official Yii2 advanced application template:
|
the official Yii2 advanced application template:
|
||||||
|
|
||||||
@ -127,6 +144,7 @@ See also all the possible configuration options available:
|
|||||||
- [Console Commands](installation/console-commands.md)
|
- [Console Commands](installation/console-commands.md)
|
||||||
- [Mailer](installation/mailer.md)
|
- [Mailer](installation/mailer.md)
|
||||||
- [Available Actions](installation/available-actions.md)
|
- [Available Actions](installation/available-actions.md)
|
||||||
|
- [Migration guide from Dektrium tools](installation/migration-guide-from-dektrium-tools.md)
|
||||||
|
|
||||||
Enhancing and Overriding
|
Enhancing and Overriding
|
||||||
------------------------
|
------------------------
|
||||||
@ -171,4 +189,4 @@ Contributing
|
|||||||
- [How to Contribute](contributing/how-to.md)
|
- [How to Contribute](contributing/how-to.md)
|
||||||
- [Clean Code](contributing/clean-code.md)
|
- [Clean Code](contributing/clean-code.md)
|
||||||
|
|
||||||
© [2amigos](http://www.2amigos.us/) 2013-2017
|
© [2amigos](http://www.2amigos.us/) 2013-2018
|
||||||
|
|||||||
@ -12,7 +12,7 @@ packages, and everything you need to start project in no time with batteries inc
|
|||||||
> [Check this manual page](sidekit-application-template.md) if you decided to use it.
|
> [Check this manual page](sidekit-application-template.md) if you decided to use it.
|
||||||
|
|
||||||
If you want to use the default [Basic Application Template](https://github.com/yiisoft/yii2-app-basic) with our
|
If you want to use the default [Basic Application Template](https://github.com/yiisoft/yii2-app-basic) with our
|
||||||
extension, then check [Basic Application Template documentation page](basic-application-template.md).
|
extension, then check [Basic Application Template documentation page](yii2-application-template.md).
|
||||||
|
|
||||||
Step 1 - Install Advanced Application template
|
Step 1 - Install Advanced Application template
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|||||||
@ -48,6 +48,25 @@ If `true` it will enable password recovery process.
|
|||||||
If `true` and `allowPasswordRecovery` is false, it will enable administrator to send a password recovery email to a
|
If `true` and `allowPasswordRecovery` is false, it will enable administrator to send a password recovery email to a
|
||||||
user.
|
user.
|
||||||
|
|
||||||
|
#### maxPasswordAge (type: `integer`, default: `null`)
|
||||||
|
|
||||||
|
If set to an integer value it will check user password age. If the days since last password change are greater than this configuration value
|
||||||
|
user will be forced to change it. This enforcement is done only at login stage. In order to perform the check in every action you must configure
|
||||||
|
a filter into your controller like this:
|
||||||
|
```
|
||||||
|
use Da\User\Filter\PasswordAgeEnforceFilter;
|
||||||
|
class SiteController extends Controller
|
||||||
|
{
|
||||||
|
public function behaviors()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[...]
|
||||||
|
'enforcePasswordAge' => [
|
||||||
|
'class' => PasswordAgeEnforceFilter::className(),
|
||||||
|
],
|
||||||
|
```
|
||||||
|
This will redirect the user to their account page until the password has been updated.
|
||||||
|
|
||||||
#### allowAccountDelete (type: `boolean`, default: `true`)
|
#### allowAccountDelete (type: `boolean`, default: `true`)
|
||||||
|
|
||||||
If `true` users will be able to remove their own accounts.
|
If `true` users will be able to remove their own accounts.
|
||||||
|
|||||||
387
docs/installation/migration-guide-from-dektrium-tools.md
Normal file
387
docs/installation/migration-guide-from-dektrium-tools.md
Normal file
@ -0,0 +1,387 @@
|
|||||||
|
# Migration guide from Dektrium tools
|
||||||
|
|
||||||
|
yii2-usuario is 99% compatible with [dektrium](https://github.com/dektrium/) tools.
|
||||||
|
|
||||||
|
## Package removal
|
||||||
|
|
||||||
|
First of all you need to remove the old packages. Depending on your installation you
|
||||||
|
need to remove one or both:
|
||||||
|
```
|
||||||
|
composer remove dektrium/yii2-user
|
||||||
|
composer remove dektrium/yii2-rbac
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Configure the `config/console.php` stuff:
|
||||||
|
|
||||||
|
```php
|
||||||
|
'authManager' => [
|
||||||
|
'class' => 'yii\rbac\DbManager',
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure the controller map for migrations
|
||||||
|
|
||||||
|
```php
|
||||||
|
'controllerMap' => [
|
||||||
|
'migrate' => [
|
||||||
|
'class' => 'yii\console\controllers\MigrateController',
|
||||||
|
'migrationNamespaces' => [
|
||||||
|
'Da\User\Migration',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
Remove the *modules > rbac* configuration parameter, and replace the value of *modules > user* with:
|
||||||
|
```php
|
||||||
|
'user' => Da\User\Module::class,
|
||||||
|
```
|
||||||
|
|
||||||
|
In `config/web.php` remove *module > rbac* configuration and change the *modules > user* with:
|
||||||
|
```php
|
||||||
|
...
|
||||||
|
'user' => [
|
||||||
|
'class' => Da\User\Module::class,
|
||||||
|
// Othe yii2-usuario configuration parameters
|
||||||
|
'enableRegistration' => false,
|
||||||
|
],
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
* If you had `modelMap` customization you have to replace them with `classMap`.
|
||||||
|
* In your extended model replace the `BaseUser` inheritance from `dektrium\user\models\User` to `Da\User\Model\User`
|
||||||
|
* If you had controller remapping replace the inheritance from `dektrium\user\controllers\XX` to `Da\User\Controller\XX`
|
||||||
|
|
||||||
|
## Rbac migrations
|
||||||
|
|
||||||
|
[yii2-rbac](https://github.com/dektrium/yii2-rbac) had a nice tool which are rbac migrations, which helped writing new permissions and roles.
|
||||||
|
There's no such feature in yii2-usuario, but in case you need to still apply them you can:
|
||||||
|
|
||||||
|
1. create a migration component which basically it's the same as the original [Migration](https://github.com/dektrium/yii2-rbac/blob/master/migrations/Migration.php) object, with some minor changes. Copy the content below and save it in your `@app/components/RbacMigration.php`:
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 app\components;
|
||||||
|
|
||||||
|
use yii\rbac\DbManager;
|
||||||
|
use yii\db\Migration;
|
||||||
|
use yii\di\Instance;
|
||||||
|
use yii\rbac\Item;
|
||||||
|
use yii\rbac\Permission;
|
||||||
|
use yii\rbac\Role;
|
||||||
|
use yii\rbac\Rule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migration for applying new RBAC items.
|
||||||
|
*
|
||||||
|
* @author Dmitry Erofeev <dmeroff@gmail.com>
|
||||||
|
*/
|
||||||
|
class RbacMigration extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string|DbManager The auth manager component ID that this migration should work with.
|
||||||
|
*/
|
||||||
|
public $authManager = 'authManager';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the migration.
|
||||||
|
* This method will set [[authManager]] to be the 'authManager' application component, if it is `null`.
|
||||||
|
*/
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
parent::init();
|
||||||
|
|
||||||
|
$this->authManager = Instance::ensure($this->authManager, DbManager::className());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new permission.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the permission
|
||||||
|
* @param string $description The description of the permission
|
||||||
|
* @param string|null $ruleName The rule associated with the permission
|
||||||
|
* @param mixed|null $data The additional data associated with the permission
|
||||||
|
* @return Permission
|
||||||
|
*/
|
||||||
|
protected function createPermission($name, $description = '', $ruleName = null, $data = null)
|
||||||
|
{
|
||||||
|
echo " > create permission $name ...";
|
||||||
|
$time = microtime(true);
|
||||||
|
$permission = $this->authManager->createPermission($name);
|
||||||
|
|
||||||
|
$permission->description = $description;
|
||||||
|
$permission->ruleName = $ruleName;
|
||||||
|
$permission->data = $data;
|
||||||
|
|
||||||
|
$this->authManager->add($permission);
|
||||||
|
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
|
||||||
|
|
||||||
|
return $permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new role.
|
||||||
|
*
|
||||||
|
* @param string $name The name of the role
|
||||||
|
* @param string $description The description of the role
|
||||||
|
* @param string|null $ruleName The rule associated with the role
|
||||||
|
* @param mixed|null $data The additional data associated with the role
|
||||||
|
* @return Role
|
||||||
|
*/
|
||||||
|
protected function createRole($name, $description = '', $ruleName = null, $data = null)
|
||||||
|
{
|
||||||
|
echo " > create role $name ...";
|
||||||
|
$time = microtime(true);
|
||||||
|
$role = $this->authManager->createRole($name);
|
||||||
|
|
||||||
|
$role->description = $description;
|
||||||
|
$role->ruleName = $ruleName;
|
||||||
|
$role->data = $data;
|
||||||
|
|
||||||
|
$this->authManager->add($role);
|
||||||
|
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
|
||||||
|
|
||||||
|
return $role;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new rule.
|
||||||
|
*
|
||||||
|
* @param string $ruleName The name of the rule
|
||||||
|
* @param string|array $definition The class of the rule
|
||||||
|
* @return Rule
|
||||||
|
*/
|
||||||
|
protected function createRule($ruleName, $definition)
|
||||||
|
{
|
||||||
|
echo " > create rule $ruleName ...";
|
||||||
|
$time = microtime(true);
|
||||||
|
|
||||||
|
if (is_array($definition)) {
|
||||||
|
$definition['name'] = $ruleName;
|
||||||
|
} else {
|
||||||
|
$definition = [
|
||||||
|
'class' => $definition,
|
||||||
|
'name' => $ruleName,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Rule $rule */
|
||||||
|
$rule = \Yii::createObject($definition);
|
||||||
|
|
||||||
|
$this->authManager->add($rule);
|
||||||
|
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
|
||||||
|
|
||||||
|
return $rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds either role or permission or throws an exception if it is not found.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return Permission|Role|null
|
||||||
|
*/
|
||||||
|
protected function findItem($name)
|
||||||
|
{
|
||||||
|
$item = $this->authManager->getRole($name);
|
||||||
|
|
||||||
|
if ($item instanceof Role) {
|
||||||
|
return $item;
|
||||||
|
}
|
||||||
|
|
||||||
|
$item = $this->authManager->getPermission($name);
|
||||||
|
|
||||||
|
if ($item instanceof Permission) {
|
||||||
|
return $item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the role or throws an exception if it is not found.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return Role|null
|
||||||
|
*/
|
||||||
|
protected function findRole($name)
|
||||||
|
{
|
||||||
|
$role = $this->authManager->getRole($name);
|
||||||
|
|
||||||
|
if ($role instanceof Role) {
|
||||||
|
return $role;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the permission or throws an exception if it is not found.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return Permission|null
|
||||||
|
*/
|
||||||
|
protected function findPermission($name)
|
||||||
|
{
|
||||||
|
$permission = $this->authManager->getPermission($name);
|
||||||
|
|
||||||
|
if ($permission instanceof Permission) {
|
||||||
|
return $permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes auth item.
|
||||||
|
*
|
||||||
|
* @param string|Item $item Either item name or item instance to be removed.
|
||||||
|
*/
|
||||||
|
protected function removeItem($item)
|
||||||
|
{
|
||||||
|
if (is_string($item)) {
|
||||||
|
$item = $this->findItem($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo " > removing $item->name ...";
|
||||||
|
$time = microtime(true);
|
||||||
|
$this->authManager->remove($item);
|
||||||
|
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds child.
|
||||||
|
*
|
||||||
|
* @param Item|string $parent Either name or Item instance which is parent
|
||||||
|
* @param Item|string $child Either name or Item instance which is child
|
||||||
|
*/
|
||||||
|
protected function addChild($parent, $child)
|
||||||
|
{
|
||||||
|
if (is_string($parent)) {
|
||||||
|
$parent = $this->findItem($parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_string($child)) {
|
||||||
|
$child = $this->findItem($child);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo " > adding $child->name as child to $parent->name ...";
|
||||||
|
$time = microtime(true);
|
||||||
|
$this->authManager->addChild($parent, $child);
|
||||||
|
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a role to a user.
|
||||||
|
*
|
||||||
|
* @param string|Role $role
|
||||||
|
* @param string|int $userId
|
||||||
|
*/
|
||||||
|
protected function assign($role, $userId)
|
||||||
|
{
|
||||||
|
if (is_string($role)) {
|
||||||
|
$role = $this->findRole($role);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo " > assigning $role->name to user $userId ...";
|
||||||
|
$time = microtime(true);
|
||||||
|
$this->authManager->assign($role, $userId);
|
||||||
|
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates role.
|
||||||
|
*
|
||||||
|
* @param string|Role $role
|
||||||
|
* @param string $description
|
||||||
|
* @param string $ruleName
|
||||||
|
* @param mixed $data
|
||||||
|
* @return Role
|
||||||
|
*/
|
||||||
|
protected function updateRole($role, $description = '', $ruleName = null, $data = null)
|
||||||
|
{
|
||||||
|
if (is_string($role)) {
|
||||||
|
$role = $this->findRole($role);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo " > update role $role->name ...";
|
||||||
|
$time = microtime(true);
|
||||||
|
|
||||||
|
$role->description = $description;
|
||||||
|
$role->ruleName = $ruleName;
|
||||||
|
$role->data = $data;
|
||||||
|
|
||||||
|
$this->authManager->update($role->name, $role);
|
||||||
|
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
|
||||||
|
|
||||||
|
return $role;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates permission.
|
||||||
|
*
|
||||||
|
* @param string|Permission $permission
|
||||||
|
* @param string $description
|
||||||
|
* @param string $ruleName
|
||||||
|
* @param mixed $data
|
||||||
|
* @return Permission
|
||||||
|
*/
|
||||||
|
protected function updatePermission($permission, $description = '', $ruleName = null, $data = null)
|
||||||
|
{
|
||||||
|
if (is_string($permission)) {
|
||||||
|
$permission = $this->findPermission($permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo " > update permission $permission->name ...";
|
||||||
|
$time = microtime(true);
|
||||||
|
|
||||||
|
$permission->description = $description;
|
||||||
|
$permission->ruleName = $ruleName;
|
||||||
|
$permission->data = $data;
|
||||||
|
|
||||||
|
$this->authManager->update($permission->name, $permission);
|
||||||
|
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
|
||||||
|
|
||||||
|
return $permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates rule.
|
||||||
|
*
|
||||||
|
* @param string $ruleName
|
||||||
|
* @param string $className
|
||||||
|
* @return Rule
|
||||||
|
*/
|
||||||
|
protected function updateRule($ruleName, $className)
|
||||||
|
{
|
||||||
|
echo " > update rule $ruleName ...";
|
||||||
|
$time = microtime(true);
|
||||||
|
|
||||||
|
/** @var Rule $rule */
|
||||||
|
$rule = \Yii::createObject([
|
||||||
|
'class' => $className,
|
||||||
|
'name' => $ruleName,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->authManager->update($ruleName, $rule);
|
||||||
|
echo ' done (time: ' . sprintf('%.3f', microtime(true) - $time) . "s)\n";
|
||||||
|
|
||||||
|
return $rule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
2. change the inheritance of the `@app/rbac/migrations` files to `app\components\RbacMigration as Migration`
|
||||||
|
|
||||||
|
... and you're done! You can still apply your rbac migrations with `./yii migrate/up --migrationPath=@yii/rbac/migrations`.
|
||||||
@ -25,6 +25,10 @@ use yii\console\Application as ConsoleApplication;
|
|||||||
use yii\i18n\PhpMessageSource;
|
use yii\i18n\PhpMessageSource;
|
||||||
use yii\web\Application as WebApplication;
|
use yii\web\Application as WebApplication;
|
||||||
|
|
||||||
|
use yii\base\Event;
|
||||||
|
use Da\User\Event\FormEvent;
|
||||||
|
use Da\User\Controller\SecurityController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bootstrap class of the yii2-usuario extension. Configures container services, initializes translations,
|
* Bootstrap class of the yii2-usuario extension. Configures container services, initializes translations,
|
||||||
* builds class map, and does the other setup actions participating in the application bootstrap process.
|
* builds class map, and does the other setup actions participating in the application bootstrap process.
|
||||||
@ -91,6 +95,7 @@ class Bootstrap implements BootstrapInterface
|
|||||||
// services
|
// services
|
||||||
$di->set(Service\AccountConfirmationService::class);
|
$di->set(Service\AccountConfirmationService::class);
|
||||||
$di->set(Service\EmailChangeService::class);
|
$di->set(Service\EmailChangeService::class);
|
||||||
|
$di->set(Service\PasswordExpireService::class);
|
||||||
$di->set(Service\PasswordRecoveryService::class);
|
$di->set(Service\PasswordRecoveryService::class);
|
||||||
$di->set(Service\ResendConfirmationService::class);
|
$di->set(Service\ResendConfirmationService::class);
|
||||||
$di->set(Service\ResetPasswordService::class);
|
$di->set(Service\ResetPasswordService::class);
|
||||||
@ -144,12 +149,24 @@ class Bootstrap implements BootstrapInterface
|
|||||||
$di->set(Search\RoleSearch::class);
|
$di->set(Search\RoleSearch::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attach an event to check if the password has expired
|
||||||
|
if (!is_null(Yii::$app->getModule('user')->maxPasswordAge)) {
|
||||||
|
Event::on(SecurityController::class, FormEvent::EVENT_AFTER_LOGIN, function (FormEvent $event) {
|
||||||
|
$user = $event->form->user;
|
||||||
|
if ($user->password_age >= Yii::$app->getModule('user')->maxPasswordAge) {
|
||||||
|
// Force password change
|
||||||
|
Yii::$app->session->setFlash('warning', Yii::t('usuario', 'Your password has expired, you must change it now'));
|
||||||
|
Yii::$app->response->redirect(['/user/settings/account'])->send();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if ($app instanceof WebApplication) {
|
if ($app instanceof WebApplication) {
|
||||||
// override Yii
|
// override Yii
|
||||||
$di->set(
|
$di->set(
|
||||||
'yii\web\User',
|
'yii\web\User',
|
||||||
[
|
[
|
||||||
'enableAutoLogin' => $app->getModule('user')->enableAutologin,
|
'enableAutoLogin' => $app->getModule('user')->enableAutoLogin,
|
||||||
'loginUrl' => ['/user/security/login'],
|
'loginUrl' => ['/user/security/login'],
|
||||||
'identityClass' => $di->get(ClassMapHelper::class)->get(User::class),
|
'identityClass' => $di->get(ClassMapHelper::class)->get(User::class),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -18,6 +18,7 @@ use Da\User\Model\Profile;
|
|||||||
use Da\User\Model\User;
|
use Da\User\Model\User;
|
||||||
use Da\User\Query\UserQuery;
|
use Da\User\Query\UserQuery;
|
||||||
use Da\User\Search\UserSearch;
|
use Da\User\Search\UserSearch;
|
||||||
|
use Da\User\Service\PasswordExpireService;
|
||||||
use Da\User\Service\PasswordRecoveryService;
|
use Da\User\Service\PasswordRecoveryService;
|
||||||
use Da\User\Service\SwitchIdentityService;
|
use Da\User\Service\SwitchIdentityService;
|
||||||
use Da\User\Service\UserBlockService;
|
use Da\User\Service\UserBlockService;
|
||||||
@ -328,4 +329,20 @@ class AdminController extends Controller
|
|||||||
|
|
||||||
return $this->redirect(['index']);
|
return $this->redirect(['index']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces the user to change password at next login
|
||||||
|
* @param integer $id
|
||||||
|
*/
|
||||||
|
public function actionForcePasswordChange($id)
|
||||||
|
{
|
||||||
|
/** @var User $user */
|
||||||
|
$user = $this->userQuery->where(['id' => $id])->one();
|
||||||
|
if ($this->make(PasswordExpireService::class, [$user])->run()) {
|
||||||
|
Yii::$app->session->setFlash("success", Yii::t('usuario', 'User will be required to change password at next login'));
|
||||||
|
} else {
|
||||||
|
Yii::$app->session->setFlash("danger", Yii::t('usuario', 'There was an error in saving user'));
|
||||||
|
}
|
||||||
|
$this->redirect(['index']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,6 +106,7 @@ class RegistrationController extends Controller
|
|||||||
$mailService = MailFactory::makeWelcomeMailerService($user);
|
$mailService = MailFactory::makeWelcomeMailerService($user);
|
||||||
|
|
||||||
if ($this->make(UserRegisterService::class, [$user, $mailService])->run()) {
|
if ($this->make(UserRegisterService::class, [$user, $mailService])->run()) {
|
||||||
|
if ($this->module->enableEmailConfirmation) {
|
||||||
Yii::$app->session->setFlash(
|
Yii::$app->session->setFlash(
|
||||||
'info',
|
'info',
|
||||||
Yii::t(
|
Yii::t(
|
||||||
@ -113,6 +114,9 @@ class RegistrationController extends Controller
|
|||||||
'Your account has been created and a message with further instructions has been sent to your email'
|
'Your account has been created and a message with further instructions has been sent to your email'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
Yii::$app->session->setFlash('info', Yii::t('usuario', 'Your account has been created'));
|
||||||
|
}
|
||||||
$this->trigger(FormEvent::EVENT_AFTER_REGISTER, $event);
|
$this->trigger(FormEvent::EVENT_AFTER_REGISTER, $event);
|
||||||
return $this->render(
|
return $this->render(
|
||||||
'/shared/message',
|
'/shared/message',
|
||||||
|
|||||||
39
src/User/Filter/PasswordAgeEnforceFilter.php
Normal file
39
src/User/Filter/PasswordAgeEnforceFilter.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the 2amigos/yii2-usuario project.
|
||||||
|
*
|
||||||
|
* (c) 2amigOS! <http://2amigos.us/>
|
||||||
|
* @author Lorenzo Milesi <maxxer@yetopen.it>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Da\User\Filter;
|
||||||
|
|
||||||
|
use Yii;
|
||||||
|
use yii\base\ActionFilter;
|
||||||
|
|
||||||
|
class PasswordAgeEnforceFilter extends ActionFilter
|
||||||
|
{
|
||||||
|
public function beforeAction($action)
|
||||||
|
{
|
||||||
|
$maxPasswordAge = Yii::$app->getModule('user')->maxPasswordAge;
|
||||||
|
// If feature is not set do nothing (or raise a configuration error?)
|
||||||
|
if (is_null($maxPasswordAge)) {
|
||||||
|
return parent::beforeAction($action);
|
||||||
|
}
|
||||||
|
if (Yii::$app->user->isGuest) {
|
||||||
|
// Not our business
|
||||||
|
return parent::beforeAction($action);
|
||||||
|
}
|
||||||
|
if (Yii::$app->user->identity->password_age >= $maxPasswordAge) {
|
||||||
|
// Force password change
|
||||||
|
Yii::$app->getSession()->setFlash('warning', Yii::t('usuario', 'Your password has expired, you must change it now'));
|
||||||
|
return Yii::$app->response->redirect(['/user/settings/account'])->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::beforeAction($action);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the 2amigos/yii2-usuario project.
|
||||||
|
*
|
||||||
|
* (c) 2amigOS! <http://2amigos.us/>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Da\User\Migration;
|
||||||
|
|
||||||
|
use yii\db\Migration;
|
||||||
|
|
||||||
|
class m000000_000007_enable_password_expiration extends Migration
|
||||||
|
{
|
||||||
|
public function safeUp()
|
||||||
|
{
|
||||||
|
$this->addColumn('{{%user}}', 'password_changed_at', $this->integer()->null());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function safeDown()
|
||||||
|
{
|
||||||
|
$this->dropColumn('{{%user}}', 'password_changed_at');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -22,6 +22,7 @@ use yii\base\InvalidParamException;
|
|||||||
use yii\base\NotSupportedException;
|
use yii\base\NotSupportedException;
|
||||||
use yii\behaviors\TimestampBehavior;
|
use yii\behaviors\TimestampBehavior;
|
||||||
use yii\db\ActiveRecord;
|
use yii\db\ActiveRecord;
|
||||||
|
use yii\db\Expression;
|
||||||
use yii\helpers\ArrayHelper;
|
use yii\helpers\ArrayHelper;
|
||||||
use yii\web\Application;
|
use yii\web\Application;
|
||||||
use yii\web\IdentityInterface;
|
use yii\web\IdentityInterface;
|
||||||
@ -49,6 +50,8 @@ use yii\web\IdentityInterface;
|
|||||||
* @property int $created_at
|
* @property int $created_at
|
||||||
* @property int $updated_at
|
* @property int $updated_at
|
||||||
* @property int $last_login_at
|
* @property int $last_login_at
|
||||||
|
* @property int $password_changed_at
|
||||||
|
* @property int $password_age
|
||||||
*
|
*
|
||||||
* Defined relations:
|
* Defined relations:
|
||||||
* @property SocialNetworkAccount[] $socialNetworkAccounts
|
* @property SocialNetworkAccount[] $socialNetworkAccounts
|
||||||
@ -95,6 +98,7 @@ class User extends ActiveRecord implements IdentityInterface
|
|||||||
'password_hash',
|
'password_hash',
|
||||||
$security->generatePasswordHash($this->password, $this->getModule()->blowfishCost)
|
$security->generatePasswordHash($this->password, $this->getModule()->blowfishCost)
|
||||||
);
|
);
|
||||||
|
$this->password_changed_at = time();
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::beforeSave($insert);
|
return parent::beforeSave($insert);
|
||||||
@ -147,6 +151,8 @@ class User extends ActiveRecord implements IdentityInterface
|
|||||||
'created_at' => Yii::t('usuario', 'Registration time'),
|
'created_at' => Yii::t('usuario', 'Registration time'),
|
||||||
'confirmed_at' => Yii::t('usuario', 'Confirmation time'),
|
'confirmed_at' => Yii::t('usuario', 'Confirmation time'),
|
||||||
'last_login_at' => Yii::t('usuario', 'Last login'),
|
'last_login_at' => Yii::t('usuario', 'Last login'),
|
||||||
|
'password_changed_at' => Yii::t('usuario', 'Last password change'),
|
||||||
|
'password_age' => Yii::t('usuario', 'Password age'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +181,7 @@ class User extends ActiveRecord implements IdentityInterface
|
|||||||
return [
|
return [
|
||||||
// username rules
|
// username rules
|
||||||
'usernameRequired' => ['username', 'required', 'on' => ['register', 'create', 'connect', 'update']],
|
'usernameRequired' => ['username', 'required', 'on' => ['register', 'create', 'connect', 'update']],
|
||||||
'usernameMatch' => ['username', 'match', 'pattern' => '/^[-a-zA-Z0-9_\.@]+$/'],
|
'usernameMatch' => ['username', 'match', 'pattern' => '/^[-a-zA-Z0-9_\.@\+]+$/'],
|
||||||
'usernameLength' => ['username', 'string', 'min' => 3, 'max' => 255],
|
'usernameLength' => ['username', 'string', 'min' => 3, 'max' => 255],
|
||||||
'usernameTrim' => ['username', 'trim'],
|
'usernameTrim' => ['username', 'trim'],
|
||||||
'usernameUnique' => [
|
'usernameUnique' => [
|
||||||
@ -328,4 +334,17 @@ class User extends ActiveRecord implements IdentityInterface
|
|||||||
{
|
{
|
||||||
throw new NotSupportedException('Method "' . __CLASS__ . '::' . __METHOD__ . '" is not implemented.');
|
throw new NotSupportedException('Method "' . __CLASS__ . '::' . __METHOD__ . '" is not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns password age in days
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getPassword_age()
|
||||||
|
{
|
||||||
|
if (is_null($this->password_changed_at)) {
|
||||||
|
return $this->getModule()->maxPasswordAge;
|
||||||
|
}
|
||||||
|
$d = new \DateTime("@{$this->password_changed_at}");
|
||||||
|
return $d->diff(new \DateTime(), true)->format("%a");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,9 +29,9 @@ class Module extends BaseModule
|
|||||||
*/
|
*/
|
||||||
public $twoFactorAuthenticationCycles = 1;
|
public $twoFactorAuthenticationCycles = 1;
|
||||||
/**
|
/**
|
||||||
* @var bool whether to allow autologin or not
|
* @var bool whether to allow auto login or not
|
||||||
*/
|
*/
|
||||||
public $enableAutologin = true;
|
public $enableAutoLogin = true;
|
||||||
/**
|
/**
|
||||||
* @var bool whether to allow registration process or not
|
* @var bool whether to allow registration process or not
|
||||||
*/
|
*/
|
||||||
@ -132,4 +132,8 @@ class Module extends BaseModule
|
|||||||
* @var string the session key name to impersonate users. Please, modify it for security reasons!
|
* @var string the session key name to impersonate users. Please, modify it for security reasons!
|
||||||
*/
|
*/
|
||||||
public $switchIdentitySessionKey = 'yuik_usuario';
|
public $switchIdentitySessionKey = 'yuik_usuario';
|
||||||
|
/**
|
||||||
|
* @var integer If != NULL sets a max password age in days
|
||||||
|
*/
|
||||||
|
public $maxPasswordAge = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,8 +66,6 @@ class RuleSearch extends Rule
|
|||||||
|
|
||||||
if (!$this->validate()) {
|
if (!$this->validate()) {
|
||||||
$query->where('0=1');
|
$query->where('0=1');
|
||||||
var_dump($this->load($params));
|
|
||||||
die();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->make(
|
return $this->make(
|
||||||
|
|||||||
30
src/User/Service/PasswordExpireService.php
Normal file
30
src/User/Service/PasswordExpireService.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the 2amigos/yii2-usuario project.
|
||||||
|
*
|
||||||
|
* (c) 2amigOS! <http://2amigos.us/>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Da\User\Service;
|
||||||
|
|
||||||
|
use Da\User\Contracts\ServiceInterface;
|
||||||
|
use Da\User\Model\User;
|
||||||
|
|
||||||
|
class PasswordExpireService implements ServiceInterface
|
||||||
|
{
|
||||||
|
protected $model;
|
||||||
|
|
||||||
|
public function __construct(User $model)
|
||||||
|
{
|
||||||
|
$this->model = $model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
return $this->model->updateAttributes(['last_login_at' => time()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,12 +16,14 @@ use Da\User\Factory\TokenFactory;
|
|||||||
use Da\User\Model\User;
|
use Da\User\Model\User;
|
||||||
use Da\User\Query\UserQuery;
|
use Da\User\Query\UserQuery;
|
||||||
use Da\User\Traits\MailAwareTrait;
|
use Da\User\Traits\MailAwareTrait;
|
||||||
|
use Da\User\Traits\ModuleAwareTrait;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Yii;
|
use Yii;
|
||||||
|
|
||||||
class PasswordRecoveryService implements ServiceInterface
|
class PasswordRecoveryService implements ServiceInterface
|
||||||
{
|
{
|
||||||
use MailAwareTrait;
|
use MailAwareTrait;
|
||||||
|
use ModuleAwareTrait;
|
||||||
|
|
||||||
protected $query;
|
protected $query;
|
||||||
|
|
||||||
@ -58,10 +60,12 @@ class PasswordRecoveryService implements ServiceInterface
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->getModule()->enableFlashMessages == true) {
|
||||||
Yii::$app->session->setFlash(
|
Yii::$app->session->setFlash(
|
||||||
'info',
|
'info',
|
||||||
Yii::t('usuario', 'An email has been sent with instructions for resetting your password')
|
Yii::t('usuario', 'An email has been sent with instructions for resetting your password')
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
|||||||
@ -14,9 +14,12 @@ namespace Da\User\Service;
|
|||||||
use Da\User\Contracts\ServiceInterface;
|
use Da\User\Contracts\ServiceInterface;
|
||||||
use Da\User\Event\UserEvent;
|
use Da\User\Event\UserEvent;
|
||||||
use Da\User\Model\User;
|
use Da\User\Model\User;
|
||||||
|
use Da\User\Traits\MailAwareTrait;
|
||||||
|
|
||||||
class UserConfirmationService implements ServiceInterface
|
class UserConfirmationService implements ServiceInterface
|
||||||
{
|
{
|
||||||
|
use MailAwareTrait;
|
||||||
|
|
||||||
protected $model;
|
protected $model;
|
||||||
|
|
||||||
public function __construct(User $model)
|
public function __construct(User $model)
|
||||||
@ -26,9 +29,12 @@ class UserConfirmationService implements ServiceInterface
|
|||||||
|
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
$this->model->trigger(UserEvent::EVENT_BEFORE_CONFIRMATION);
|
$model = $this->model;
|
||||||
|
$event = $this->make(UserEvent::class, [$model]);
|
||||||
|
|
||||||
|
$this->model->trigger(UserEvent::EVENT_BEFORE_CONFIRMATION, $event);
|
||||||
if ((bool)$this->model->updateAttributes(['confirmed_at' => time()])) {
|
if ((bool)$this->model->updateAttributes(['confirmed_at' => time()])) {
|
||||||
$this->model->trigger(UserEvent::EVENT_AFTER_CONFIRMATION);
|
$this->model->trigger(UserEvent::EVENT_AFTER_CONFIRMATION, $event);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,14 +57,15 @@ class UserCreateService implements ServiceInterface
|
|||||||
? $model->password
|
? $model->password
|
||||||
: $this->securityHelper->generatePassword(8);
|
: $this->securityHelper->generatePassword(8);
|
||||||
|
|
||||||
$model->trigger(UserEvent::EVENT_BEFORE_CREATE);
|
$event = $this->make(UserEvent::class, [$model]);
|
||||||
|
$model->trigger(UserEvent::EVENT_BEFORE_CREATE, $event);
|
||||||
|
|
||||||
if (!$model->save()) {
|
if (!$model->save()) {
|
||||||
$transaction->rollBack();
|
$transaction->rollBack();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$model->trigger(UserEvent::EVENT_AFTER_CREATE);
|
$model->trigger(UserEvent::EVENT_AFTER_CREATE, $event);
|
||||||
if (!$this->sendMail($model)) {
|
if (!$this->sendMail($model)) {
|
||||||
Yii::$app->session->setFlash(
|
Yii::$app->session->setFlash(
|
||||||
'warning',
|
'warning',
|
||||||
|
|||||||
@ -54,7 +54,7 @@ class ReCaptchaWidget extends InputWidget
|
|||||||
*/
|
*/
|
||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
if (Yii::$app->get('recaptcha')) {
|
if (!Yii::$app->get('recaptcha')) {
|
||||||
throw new InvalidConfigException(Yii::t('usuario', 'The "recaptcha" component must be configured.'));
|
throw new InvalidConfigException(Yii::t('usuario', 'The "recaptcha" component must be configured.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -92,6 +92,7 @@ $module = Yii::$app->getModule('user');
|
|||||||
'format' => 'raw',
|
'format' => 'raw',
|
||||||
'visible' => Yii::$app->getModule('user')->enableEmailConfirmation,
|
'visible' => Yii::$app->getModule('user')->enableEmailConfirmation,
|
||||||
],
|
],
|
||||||
|
'password_age',
|
||||||
[
|
[
|
||||||
'header' => Yii::t('usuario', 'Block status'),
|
'header' => Yii::t('usuario', 'Block status'),
|
||||||
'value' => function ($model) {
|
'value' => function ($model) {
|
||||||
@ -121,7 +122,7 @@ $module = Yii::$app->getModule('user');
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'class' => 'yii\grid\ActionColumn',
|
'class' => 'yii\grid\ActionColumn',
|
||||||
'template' => '{switch} {reset} {update} {delete}',
|
'template' => '{switch} {reset} {force-password-change} {update} {delete}',
|
||||||
'buttons' => [
|
'buttons' => [
|
||||||
'switch' => function ($url, $model) use ($module) {
|
'switch' => function ($url, $model) use ($module) {
|
||||||
if ($model->id != Yii::$app->user->id && $module->enableSwitchIdentities) {
|
if ($model->id != Yii::$app->user->id && $module->enableSwitchIdentities) {
|
||||||
@ -157,8 +158,25 @@ $module = Yii::$app->getModule('user');
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
'force-password-change' => function ($url, $model) use ($module) {
|
||||||
|
if (is_null($module->maxPasswordAge)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
return Html::a(
|
||||||
|
'<span class="glyphicon glyphicon-time"></span>',
|
||||||
|
['/user/admin/force-password-change', 'id' => $model->id],
|
||||||
|
[
|
||||||
|
'title' => Yii::t('usuario', 'Force password change at next login'),
|
||||||
|
'data-confirm' => Yii::t(
|
||||||
|
'usuario',
|
||||||
|
'Are you sure you wish the user to change their password at next login?'
|
||||||
|
),
|
||||||
|
'data-method' => 'POST',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
},
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|||||||
@ -73,6 +73,7 @@ CREATE TABLE `user` (
|
|||||||
`auth_tf_enabled` tinyint(1) DEFAULT '0',
|
`auth_tf_enabled` tinyint(1) DEFAULT '0',
|
||||||
`flags` int(11) NOT NULL DEFAULT '0',
|
`flags` int(11) NOT NULL DEFAULT '0',
|
||||||
`last_login_at` int(11) DEFAULT NULL,
|
`last_login_at` int(11) DEFAULT NULL,
|
||||||
|
`password_changed_at` int(11) DEFAULT NULL,
|
||||||
|
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `user_unique_email` (`email`),
|
UNIQUE KEY `user_unique_email` (`email`),
|
||||||
|
|||||||
@ -50,7 +50,7 @@ class RegistrationCest
|
|||||||
$I->see(Html::encode('This email address has already been taken'));
|
$I->see(Html::encode('This email address has already been taken'));
|
||||||
|
|
||||||
$this->register($I, 'tester@example.com', 'tester', 'tester');
|
$this->register($I, 'tester@example.com', 'tester', 'tester');
|
||||||
$I->see('Your account has been created and a message with further instructions has been sent to your email');
|
$I->see('Your account has been created');
|
||||||
$user = $I->grabRecord(User::className(), ['email' => 'tester@example.com']);
|
$user = $I->grabRecord(User::className(), ['email' => 'tester@example.com']);
|
||||||
$I->assertTrue($user->isConfirmed);
|
$I->assertTrue($user->isConfirmed);
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ class RegistrationCest
|
|||||||
]);
|
]);
|
||||||
$I->amOnRoute('/user/registration/register');
|
$I->amOnRoute('/user/registration/register');
|
||||||
$this->register($I, 'tester@example.com', 'tester');
|
$this->register($I, 'tester@example.com', 'tester');
|
||||||
$I->see('Your account has been created and a message with further instructions has been sent to your email');
|
$I->see('Your account has been created');
|
||||||
$user = $I->grabRecord(User::className(), ['email' => 'tester@example.com']);
|
$user = $I->grabRecord(User::className(), ['email' => 'tester@example.com']);
|
||||||
$I->assertEquals('tester', $user->username);
|
$I->assertEquals('tester', $user->username);
|
||||||
/** @var yii\swiftmailer\Message $message */
|
/** @var yii\swiftmailer\Message $message */
|
||||||
|
|||||||
Reference in New Issue
Block a user