diff --git a/.gitignore b/.gitignore index 1f8808c..50f7380 100644 --- a/.gitignore +++ b/.gitignore @@ -47,8 +47,7 @@ codeception.yml # Code Style Checkers and Mess Detectors /phpcs.xml -/.php_cs.cache -/.php_cs +.php-cs-fixer.cache # composer composer.lock diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 0000000..c43072a --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,43 @@ + + +For the full copyright and license information, please view +the LICENSE file that was distributed with this source code. +EOF; + + +$finder = PhpCsFixer\Finder::create() + ->exclude(['resources']) + ->in("src/User") +; + +$config = new PhpCsFixer\Config(); +return $config->setRules([ + '@PSR1' => true, + '@PSR2' => true, + 'array_syntax' => ['syntax' => 'short'], + 'header_comment' => ['header' => $header], + 'combine_consecutive_unsets' => true, + 'no_extra_blank_lines' => [ + 'tokens' => ['break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait',], + ], + 'no_useless_else' => true, + 'no_useless_return' => true, + 'ordered_class_elements' => true, + 'ordered_imports' => true, + 'phpdoc_add_missing_param_annotation' => true, + 'phpdoc_order' => true, + 'phpdoc_align' => true, + 'no_trailing_whitespace' => true, + 'no_whitespace_in_blank_line' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_whitespace_before_comma_in_array' => true, + 'trim_array_spaces' => true, + 'explicit_string_variable' => true, + 'binary_operator_spaces' => true, + ]) + ->setFinder($finder) +; diff --git a/.php_cs.dist b/.php_cs.dist deleted file mode 100644 index a9d6959..0000000 --- a/.php_cs.dist +++ /dev/null @@ -1,49 +0,0 @@ - - -For the full copyright and license information, please view -the LICENSE file that was distributed with this source code. -EOF; - -$finder = PhpCsFixer\Finder::create() - ->exclude([ - '.github', - 'docs', - 'temp', - 'tests', - 'vendor', - 'src/User/resources' - ]) - ->in(__DIR__); - - return PhpCsFixer\Config::create() - ->setRules(array( - '@PSR1' => true, - '@PSR2' => true, - 'header_comment' => ['header' => $header], - 'array_syntax' => array('syntax' => 'short'), - 'combine_consecutive_unsets' => true, - 'no_extra_consecutive_blank_lines' => array( - 'break', - 'continue', - 'extra', - 'return', - 'throw', - 'use', - 'parenthesis_brace_block', - 'square_brace_block', - 'curly_brace_block' - ), - 'no_useless_else' => true, - 'no_useless_return' => true, - 'ordered_class_elements' => true, - 'ordered_imports' => true, - 'phpdoc_add_missing_param_annotation' => true, - 'phpdoc_order' => true, - 'phpdoc_align' => true - - )) - ->setFinder($finder); diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e01f9b..0cc0aee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,73 +1,89 @@ # CHANGELOG ## 1.6.0 work in progress - - Fix replace non-working travis build with working github actions build (TonisOrmisson) - - Fix user login events not triggered on ajax requests (TonisOrmisson) - - Enh: Added minimum requirements when a new password is automatically generated (MatteoF96) - - Fix #380: Avoid rewriting AccessRule::matchRole (maxxer) - - Fix #378: Add module attribute 'disableIpLogging' (jkmssoft) - - Enh #387: Added Persian translation (hadi-aj) - - Fix #384: Delete flash messages after consuming (cgsmith) - - Enh: Added SK translations (snickom) - - Fix: allow `password_changed_at` to be saved when reseting password (p4blojf) - - Fix #430: Moved `EVENT_BEFORE_PROFILE_UPDATE` to correct place (eluhr) - - Ehn #456: Added filter to allow forcing 2FA for specific user roles (acordeddu) +**WARNING**: this release (long time due) makes a step forward in PHP +compatibility, leaving behind obsolete versions. While yii2-usuario should +still work without issues on 5.6, from now on testing and development will +look forward and manitain only >=7.4 versions. + +- Ehn: update welcome and confirmation email ending line (maxxer) +- Ehn #361: Record and manage user session history (maranqz) +- Fix: replace non-working travis build with working github actions build (TonisOrmisson) +- Fix: user login events not triggered on ajax requests (TonisOrmisson) +- Enh: Added minimum requirements when a new password is automatically generated (MatteoF96) +- Fix #380: Avoid rewriting AccessRule::matchRole (maxxer) +- Fix #378: Add module attribute 'disableIpLogging' (jkmssoft) +- Enh #387: Added Persian translation (hadi-aj) +- Fix #384: Delete flash messages after consuming (cgsmith) +- Fix #381: Renamed events in `UserEvent` to avoid conflicts with events in `FormEvent` (Slayvin) +- Enh: Added SK translations (snickom) +- Fix: allow `password_changed_at` to be saved when reseting password (p4blojf) +- Fix #430: Moved `EVENT_BEFORE_PROFILE_UPDATE` to correct place (eluhr) +- Ehn #456: Added filter to allow forcing 2FA for specific user roles (acordeddu) +- Ehn #412: Allow role names to support UTF-8 chars (4khobta) +- Ehn #448: Remove deprecated SwiftMailer, use SymfonyMailer instead (TonisOrmisson) +- Ehn #428: Translations of the placeholders in the login widget (anapaulaxenon) +- Update PHP-CS-Fixer configuration to new version (maxxer) ## 1.5.1 April 5, 2020 - - Fix #370: Extending view fix (effsoft) - - Fix #306: Add event for failed login (ivan-cc) - - Fix #347: Only pass fields known to User model in registrationControl->actionRegister() (BillHeaton) - - Fix #346: Update ReCaptcha guide to not use AJAX (BillHeaton) - - Fix #345: Update ReCaptcha guide to add scenarios() in recoveryForm (BillHeaton) - - Fix #307: Fix French translation (arollmann) - - Fix #316: Fix new response from Google OAuth Api (Julian-B90) - - Fix #321: Fix new response from LinkedIn OAuth Api (tonydspaniard) - - Fix #322: Fix boolean values in migrations for SQL server (tsdogs) - - Enh #325: Added support for sqlite3 (santilin) - - Fix #326: Fix rule for the user auth_tf_enabled field (santilin) - - Fix #290: Fix wrong email message for resending confirmation (tonydspaniard) - - Enh #269: Added help documentation to console commands (tonydspaniard) - - Fix #244: Fix forced inclusion of a suggested class (tonydspaniard) - - Fix user event triggering in admin controller (maxxer) - - Enh #331: Added Ukrainian translations (kwazaro) - - Enh #324: Added option to restrict user assignments to roles only (CheckeredFlag) - - Enh #224: Added option to require consent (eseperio) - - Enh: Added classMap for MailService (necrox87) + +- Fix #370: Extending view fix (effsoft) +- Fix #306: Add event for failed login (ivan-cc) +- Fix #347: Only pass fields known to User model in registrationControl->actionRegister() (BillHeaton) +- Fix #346: Update ReCaptcha guide to not use AJAX (BillHeaton) +- Fix #345: Update ReCaptcha guide to add scenarios() in recoveryForm (BillHeaton) +- Fix #307: Fix French translation (arollmann) +- Fix #316: Fix new response from Google OAuth Api (Julian-B90) +- Fix #321: Fix new response from LinkedIn OAuth Api (tonydspaniard) +- Fix #322: Fix boolean values in migrations for SQL server (tsdogs) +- Enh #325: Added support for sqlite3 (santilin) +- Fix #326: Fix rule for the user auth_tf_enabled field (santilin) +- Fix #290: Fix wrong email message for resending confirmation (tonydspaniard) +- Enh #269: Added help documentation to console commands (tonydspaniard) +- Fix #244: Fix forced inclusion of a suggested class (tonydspaniard) +- Fix user event triggering in admin controller (maxxer) +- Enh #331: Added Ukrainian translations (kwazaro) +- Enh #324: Added option to restrict user assignments to roles only (CheckeredFlag) +- Enh #224: Added option to require consent (eseperio) +- Enh: Added classMap for MailService (necrox87) ## 1.5.0 April 19, 2019 - - Fix: Fix condition in EmailChangeService (it was always false) (borisaeric) - - Fix #198: Updated translations by quique, bizley, TonisOrmisson, guogan, Dezinger, maxxer, wautvda, mrbig00, fabiomlferreira, WeeSee - - Fix #209: Doc fix. allowAccountDelete default value is false (Dezinger) - - Fix #211: Migration boolean default value set to FALSE instead 0 (Dezinger) - - Fix #213: Migration sql syntax fix (Dezinger) - - Ehn #131: 2FA libraries now optional (maxxer) - - Ehn #187: Add GDPR features (Eseperio) - - Enh #184: Add `last-login-ip` capture capability (kartik-v) - - Enh: Changed `View::render()` calls in views to use absolute paths (ajmedway) - - Fix #169: Fix bug in ReCaptchaComponent (BuTaMuH) - - Fix #168: Fix spelling in russian language (EvgenyOrekhov) - - Fix #195: UserCreateService: check if we're from web before setting flash message (maxxer) - - Enh: Improvements to the admin responsive design (wautvda) - - Enh: Add controller module class reference (TonisOrmisson) - - Enh: Replace the deprecated InvalidParamException in ClassMapHelper (TonisOrmisson) - - Fix #242: Add POST filter for `admin/force-password-change` action (bscheshirwork) - - Enh #251: Use `asset-packagist` instead of `fxp-asset` if you run it as a module without having a project around (bscheshirwork) - - Fix #252: Delete check for unexpected property `allowPasswordRecovery` for resend email by admin (bscheshirwork) - - Fix #254: Rename `GDPR` properties to `lowerCamelCase` style (bscheshirwork) - - Enh #253: Add PHPDoc for events class (bscheshirwork) - - Fix #258: Rename `GDPR` delete action to `lowerCamelCase`/`dash` style (bscheshirwork) - - Fix #271: Add closure support for `from` email address; Change default sender to `supportEmail` (bscheshirwork) - - Fix #276: Fix missing translatable strings - - Enh #249: Show message `email send if possible` any time on reset password request (bscheshirwork) - - Enh #282: Allows customization of controller namespace (maxxer) - - Enh #303: Added French translation (pde159) - - Fix #304: Fixed broken regex character class (CheckeredFlag) + +- Fix: Fix condition in EmailChangeService (it was always false) (borisaeric) +- Fix #198: Updated translations by quique, bizley, TonisOrmisson, guogan, Dezinger, maxxer, wautvda, mrbig00, fabiomlferreira, WeeSee +- Fix #209: Doc fix. allowAccountDelete default value is false (Dezinger) +- Fix #211: Migration boolean default value set to FALSE instead 0 (Dezinger) +- Fix #213: Migration sql syntax fix (Dezinger) +- Ehn #131: 2FA libraries now optional (maxxer) +- Ehn #187: Add GDPR features (Eseperio) +- Enh #184: Add `last-login-ip` capture capability (kartik-v) +- Enh: Changed `View::render()` calls in views to use absolute paths (ajmedway) +- Fix #169: Fix bug in ReCaptchaComponent (BuTaMuH) +- Fix #168: Fix spelling in russian language (EvgenyOrekhov) +- Fix #195: UserCreateService: check if we're from web before setting flash message (maxxer) +- Enh: Improvements to the admin responsive design (wautvda) +- Enh: Add controller module class reference (TonisOrmisson) +- Enh: Replace the deprecated InvalidParamException in ClassMapHelper (TonisOrmisson) +- Fix #242: Add POST filter for `admin/force-password-change` action (bscheshirwork) +- Enh #251: Use `asset-packagist` instead of `fxp-asset` if you run it as a module without having a project around (bscheshirwork) +- Fix #252: Delete check for unexpected property `allowPasswordRecovery` for resend email by admin (bscheshirwork) +- Fix #254: Rename `GDPR` properties to `lowerCamelCase` style (bscheshirwork) +- Enh #253: Add PHPDoc for events class (bscheshirwork) +- Fix #258: Rename `GDPR` delete action to `lowerCamelCase`/`dash` style (bscheshirwork) +- Fix #271: Add closure support for `from` email address; Change default sender to `supportEmail` (bscheshirwork) +- Fix #276: Fix missing translatable strings +- Enh #249: Show message `email send if possible` any time on reset password request (bscheshirwork) +- Enh #282: Allows customization of controller namespace (maxxer) +- Enh #303: Added French translation (pde159) +- Fix #304: Fixed broken regex character class (CheckeredFlag) ## 1.1.4 - February 19, 2018 + - 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) @@ -82,6 +98,7 @@ - Bug #110: Honor `enableFlashMessages` in `PasswordRecoveryService` (maxxer) ## 1.1.1 - November 27, 2017 + - Bug #115: Convert client_id to string because pgsql fail with type convertion (Dezinger) - Bug #119: Security fix: add AccessControl to RuleController (Dezinger) - Enh #120: 2FA i18n russian translation (Dezinger) @@ -94,6 +111,7 @@ - Enh #109: Make use of better classes names (tonydspaniard) ## 1.1.0 - October 22, 2017 + - Enh #91: Documentation for Mail events (kartik-v) - Enh #79: Enhancements to Mailer exception handling and events (kartik-v) - Fix #85: External links should open in a new tab|window (eseperio) @@ -115,14 +133,16 @@ - Fix #86: Fix view location bug (tonydspaniard) ## 1.0.13 - August 12, 2017 + - Fix #49: Fix wrong call of method make() for set attributes (MKiselev) - Enh #46: Use safeUp()/safeDown() instead up()/down() in migrations (MKiselev) - Fix #51: Typo fix rememberLoginLifeSpan to rememberLoginLifespan (MKiselev) - Fix #58: Last login fix (pappfer) ## 1.0.12 - August 6, 2017 -- Bug Fix: Modify ResetPasswordService to forcely update password_hash field (tonydspaniard) -- Bug Fix: Fixed wrong routing misspell (tonydspaniard) + +- Bug Fix: Modify ResetPasswordService to forcely update password_hash field (tonydspaniard) +- Bug Fix: Fixed wrong routing misspell (tonydspaniard) - Enh #41: Remove deprecated package yii2-codeception (tonydspaniard) - Enh #45: Added option to display the password to the welcome email (tonydspaniard) - Fix #44: Check if the password is empty instead for null value (tonydspaniard) @@ -130,15 +150,17 @@ - Fix #42: Allow setting permissions as children to roles (kurounin) ## 1.0.10-11 - July 25, 2017 + - Fix #37: Fix bower alias in test environment (tekord) - Enh #32: Added Italian Translation (maxxer) - Fix #30: Prefill username and email in SettingsForm (mattheobjornson) - Enh #39: Added `last_login_at` field to user table (pappfer) ## 1.0.9 - July 19, 2017 + - Enh #22: Added impersonation feature (tonydspaniard) -## 1.0.8 - July 16, 2017 +## 1.0.8 - July 16, 2017 - Enh #25: Added option to manage rules (tonydspaniard) - Enh #25: Added SelectizeDropDownList widget to Role and Permission forms (tonydspaniard) diff --git a/README.md b/README.md index 17aa983..664c29a 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ Yii 2 Usuario Extension [](https://packagist.org/packages/2amigos/yii2-usuario) [](https://packagist.org/packages/2amigos/yii2-usuario) [](https://github.com/2amigos/yii2-usuario/actions/) - [](//packagist.org/packages/2amigos/yii2-usuario) [](https://scrutinizer-ci.com/g/2amigos/yii2-usuario/?branch=master) diff --git a/composer.json b/composer.json index a6e4d86..df734da 100644 --- a/composer.json +++ b/composer.json @@ -44,17 +44,19 @@ "2amigos/yii2-selectize-widget": "^1.1", "yiisoft/yii2-authclient": "^2.1", "yiisoft/yii2-httpclient": "^2.0", - "yiisoft/yii2-bootstrap": "^2.0", - "yiisoft/yii2-swiftmailer": "^2.0" + "yiisoft/yii2-bootstrap": "^2.0" }, "suggest": { + "yiisoft/yii2-symfonymailer": "A mailer driver is needed to send e-mails. Older versions use abandoned Swiftmailer which can be replaced with symfonymailer", "2amigos/2fa-library": "Needed if you want to enable 2 Factor Authentication. Require version ^1.0", "2amigos/qrcode-library": "Needed if you want to enable 2FA with QR Code generation. Require version ^1.1" }, "require-dev": { "2amigos/2fa-library": "^2.0", "2amigos/qrcode-library": "^2.0", - "friendsofphp/php-cs-fixer": "^2.3", + "friendsofphp/php-cs-fixer": "^3", + "php": ">=7.4", + "yiisoft/yii2-symfonymailer": "~2.0.0", "squizlabs/php_codesniffer": "*", "phpmd/phpmd": "@stable", "codeception/verify": "^0.3.3", diff --git a/docs/events/user-events.md b/docs/events/user-events.md old mode 100644 new mode 100755 index 3c2edd2..79eac2b --- a/docs/events/user-events.md +++ b/docs/events/user-events.md @@ -20,7 +20,9 @@ On Controllers - **UserEvent::EVENT_BEFORE_UNBLOCK**: Occurs before a user is being un-blocked - **UserEvent::EVENT_AFTER_UNBLOCK**: Occurs after a user is being un-blocked - **UserEvent::EVENT_BEFORE_SWITCH_IDENTITY**: Occurs before a user is being impersonated by admin - - **UserEvent::EVENT_AFTER_SWITCH_IDENTITY**: Occurs after a user his being impersonated by admin + - **UserEvent::EVENT_AFTER_SWITCH_IDENTITY**: Occurs after a user his being impersonated by admin + - **SessionEvent::EVENT_BEFORE_TERMINATE_USER_SESSIONS** + - **SessionEvent::EVENT_AFTER_TERMINATE_USER_SESSIONS** - **RegistrationController** @@ -41,6 +43,10 @@ On Controllers - **UserEvent::EVENT_BEFORE_DELETE**: Occurs before the user account is deleted - **UserEvent::EVENT_AFTER_DELETE**: Occurs after the user account is deleted +- **SessionController** + - **SessionEvent::EVENT_BEFORE_TERMINATE_USER_SESSIONS**: Occurs before the user sessions is terminated + - **SessionEvent::EVENT_AFTER_TERMINATE_USER_SESSIONS**: Occurs after the user sessions is terminated + On Models --------- diff --git a/docs/helpful-guides/how-to-use-session-history.md b/docs/helpful-guides/how-to-use-session-history.md new file mode 100755 index 0000000..f392f8e --- /dev/null +++ b/docs/helpful-guides/how-to-use-session-history.md @@ -0,0 +1,60 @@ +How to enable session history +============================ + +Session history list user sessions. + +User can delete all sessions except current. + +Configure Module and Application +-------------------------------- + +```php + +// ... + +'modules' => [ + 'user' => [ + 'class' => Da\User\Module::class, + 'enableSessionHistory' => true, + ] +], + +// ... + +'components' => [ + 'session' => Da\User\Service\SessionHistory\SessionHistoryDecorator::class, +] + +// ... + +'container' => [ + 'singletons' => [ + Da\User\Service\SessionHistory\TerminateSessionsServiceInterface::class => Da\User\Service\SessionHistory\TerminateSessionsService::class + ] +] + +// ... + +'controllerMap' => [ + 'migrate' => [ + ... + 'migrationNamespaces' => [ + 'Da\User\Migration\Session', + ], + ], +], + +``` + +Additionally for upping migration can use +``` +./yii migrate --migrationNamespaces=Da\\User\\Migration\Session +``` + +Setting user screenshot: + + +Admin screenshot: + + +© [2amigos](http://www.2amigos.us/) 2013-2019 diff --git a/docs/helpful-guides/session-history/admin.png b/docs/helpful-guides/session-history/admin.png new file mode 100755 index 0000000..7328174 Binary files /dev/null and b/docs/helpful-guides/session-history/admin.png differ diff --git a/docs/helpful-guides/session-history/settings.png b/docs/helpful-guides/session-history/settings.png new file mode 100755 index 0000000..d226ce1 Binary files /dev/null and b/docs/helpful-guides/session-history/settings.png differ diff --git a/docs/index.md b/docs/index.md old mode 100644 new mode 100755 index 4cf2e33..f5b9517 --- a/docs/index.md +++ b/docs/index.md @@ -188,6 +188,7 @@ Helpful Guides - [How to Switch Identities](helpful-guides/how-to-switch-identities.md) - [Separate Frontend and Backend Sessions](helpful-guides/separate-frontend-and-backend-sessions.md) - [Social Network Authentication](helpful-guides/social-network-authentication.md) +- [How to Enable session history](helpful-guides/how-to-use-session-history.md) Contributing ------------ diff --git a/docs/installation/configuration-options.md b/docs/installation/configuration-options.md old mode 100644 new mode 100755 index 3b9cf50..d4bb406 --- a/docs/installation/configuration-options.md +++ b/docs/installation/configuration-options.md @@ -3,6 +3,22 @@ Configuration Options The module comes with a set of attributes to configure. The following is the list of all available options: +#### enableSessionHistory (Type: `boolean, integer`, Default value: `false`) + +If this option is to `true`, session history will be kept, [more](../helpful-guides/how-to-use-session-history.md). + +#### numberSessionHistory (Type: `boolean, integer`, Default value: `false`) + +Number of expired storing records `session history`, values: +- `false` Store all records without deleting +- `integer` Count of records for storing + +#### timeoutSessionHistory (Type: `boolean, integer`, Default value: `false`) + +How long store `session history` after expiring, values: +- `false` Store all records without deleting +- `integer` Time for storing after expiring in seconds + #### enableTwoFactorAuthentication (type: `boolean`, default: `false`) Setting this attribute will allow users to configure their login process with two-factor authentication. diff --git a/src/User/Bootstrap.php b/src/User/Bootstrap.php old mode 100644 new mode 100755 index 07a8d92..a614e7a --- a/src/User/Bootstrap.php +++ b/src/User/Bootstrap.php @@ -16,7 +16,9 @@ use Da\User\Contracts\AuthManagerInterface; use Da\User\Controller\SecurityController; use Da\User\Event\FormEvent; use Da\User\Helper\ClassMapHelper; +use Da\User\Model\SessionHistory; use Da\User\Model\User; +use Da\User\Search\SessionHistorySearch; use Yii; use yii\authclient\Collection; use yii\base\Application; @@ -128,7 +130,7 @@ class Bootstrap implements BootstrapInterface $model = is_array($definition) ? $definition['class'] : $definition; $name = substr($class, strrpos($class, '\\') + 1); $modelClassMap[$class] = $model; - if (in_array($name, ['User', 'Profile', 'Token', 'SocialNetworkAccount'])) { + if (in_array($name, ['User', 'Profile', 'Token', 'SocialNetworkAccount', 'SessionHistory'])) { $di->set( "Da\\User\\Query\\{$name}Query", function () use ($model) { @@ -315,10 +317,12 @@ class Bootstrap implements BootstrapInterface 'Assignment' => 'Da\User\Model\Assignment', 'Permission' => 'Da\User\Model\Permission', 'Role' => 'Da\User\Model\Role', + 'SessionHistory' => SessionHistory::class, // --- search 'UserSearch' => 'Da\User\Search\UserSearch', 'PermissionSearch' => 'Da\User\Search\PermissionSearch', 'RoleSearch' => 'Da\User\Search\RoleSearch', + 'SessionHistorySearch' => SessionHistorySearch::class, // --- forms 'RegistrationForm' => 'Da\User\Form\RegistrationForm', 'ResendForm' => 'Da\User\Form\ResendForm', @@ -338,11 +342,13 @@ class Bootstrap implements BootstrapInterface 'Assignment', 'Permission', 'Role', + 'SessionHistory' ], 'Da\User\Search' => [ 'UserSearch', 'PermissionSearch', 'RoleSearch', + 'SessionHistorySearch', ], 'Da\User\Form' => [ 'RegistrationForm', @@ -359,7 +365,7 @@ class Bootstrap implements BootstrapInterface $mapping = array_merge($defaults, $userClassMap); foreach ($mapping as $name => $definition) { - $map[$this->getRoute($routes, $name) . "\\$name"] = $definition; + $map[$this->getRoute($routes, $name) . "\\{$name}"] = $definition; } return $map; diff --git a/src/User/Controller/AdminController.php b/src/User/Controller/AdminController.php old mode 100644 new mode 100755 index d8990ba..36b0d8b --- a/src/User/Controller/AdminController.php +++ b/src/User/Controller/AdminController.php @@ -17,9 +17,11 @@ use Da\User\Filter\AccessRuleFilter; use Da\User\Model\Profile; use Da\User\Model\User; use Da\User\Query\UserQuery; +use Da\User\Search\SessionHistorySearch; use Da\User\Search\UserSearch; use Da\User\Service\PasswordExpireService; use Da\User\Service\PasswordRecoveryService; +use Da\User\Service\SessionHistory\TerminateUserSessionsService; use Da\User\Service\SwitchIdentityService; use Da\User\Service\UserBlockService; use Da\User\Service\UserConfirmationService; @@ -66,7 +68,7 @@ class AdminController extends Controller */ public function beforeAction($action) { - if (in_array($action->id, ['index', 'update', 'update-profile', 'info', 'assignments'], true)) { + if (in_array($action->id, ['index', 'update', 'update-profile', 'info', 'assignments', 'session-history'], true)) { Url::remember('', 'actions-redirect'); } @@ -88,6 +90,7 @@ class AdminController extends Controller 'switch-identity' => ['post'], 'password-reset' => ['post'], 'force-password-change' => ['post'], + 'terminate-sessions' => ['post'], ], ], 'access' => [ @@ -101,6 +104,11 @@ class AdminController extends Controller 'actions' => ['switch-identity'], 'roles' => ['@'], ], + [ + 'allow' => $this->getModule()->enableSessionHistory, + 'actions' => ['session-history', 'terminate-sessions'], + 'roles' => ['admin'], + ], [ 'allow' => true, 'roles' => ['admin'], @@ -346,4 +354,33 @@ class AdminController extends Controller } $this->redirect(['index']); } + + /** + * Display list session history + */ + public function actionSessionHistory($id) + { + $searchModel = new SessionHistorySearch([ + 'user_id' => $id, + ]); + $dataProvider = $searchModel->search(Yii::$app->request->queryParams); + + $user = $this->userQuery->where(['id' => $id])->one(); + + return $this->render('_session-history', [ + 'searchModel' => $searchModel, + 'dataProvider' => $dataProvider, + 'user' => $user, + ]); + } + + /** + * Terminate all session user + */ + public function actionTerminateSessions($id) + { + $this->make(TerminateUserSessionsService::class, [$id])->run(); + + return $this->redirect(Url::previous('actions-redirect')); + } } diff --git a/src/User/Controller/RegistrationController.php b/src/User/Controller/RegistrationController.php index bad49ab..6abb039 100644 --- a/src/User/Controller/RegistrationController.php +++ b/src/User/Controller/RegistrationController.php @@ -110,13 +110,13 @@ class RegistrationController extends Controller // Create a temporay $user so we can get the attributes, then get // the intersection between the $form fields and the $user fields. - $user = $this->make(User::class, [] ); + $user = $this->make(User::class, []); $fields = array_intersect_key($form->attributes, $user->attributes); - // Becomes password_hash + // Becomes password_hash $fields['password'] = $form['password']; - $user = $this->make(User::class, [], $fields ); + $user = $this->make(User::class, [], $fields); $user->setScenario('register'); $mailService = MailFactory::makeWelcomeMailerService($user); diff --git a/src/User/Controller/SettingsController.php b/src/User/Controller/SettingsController.php old mode 100644 new mode 100755 index 0a010a5..ac88424 --- a/src/User/Controller/SettingsController.php +++ b/src/User/Controller/SettingsController.php @@ -26,7 +26,9 @@ use Da\User\Module; use Da\User\Query\ProfileQuery; use Da\User\Query\SocialNetworkAccountQuery; use Da\User\Query\UserQuery; +use Da\User\Search\SessionHistorySearch; use Da\User\Service\EmailChangeService; +use Da\User\Service\SessionHistory\TerminateUserSessionsService; use Da\User\Service\TwoFactorQrCodeUriGeneratorService; use Da\User\Traits\ContainerAwareTrait; use Da\User\Traits\ModuleAwareTrait; @@ -91,7 +93,8 @@ class SettingsController extends Controller 'actions' => [ 'disconnect' => ['post'], 'delete' => ['post'], - 'two-factor-disable' => ['post'] + 'two-factor-disable' => ['post'], + 'terminate-sessions' => ['post'], ], ], 'access' => [ @@ -111,7 +114,7 @@ class SettingsController extends Controller 'delete', 'two-factor', 'two-factor-enable', - 'two-factor-disable' + 'two-factor-disable', ], 'roles' => ['@'], ], @@ -119,7 +122,12 @@ class SettingsController extends Controller 'allow' => true, 'actions' => ['confirm'], 'roles' => ['?', '@'], - ] + ], + [ + 'allow' => $this->getModule()->enableSessionHistory, + 'actions' => ['session-history', 'terminate-sessions'], + 'roles' => ['@'], + ], ], ], ]; @@ -139,9 +147,9 @@ class SettingsController extends Controller } /** - * * - * @var ProfileEvent $event + * + * @var ProfileEvent $event */ $event = $this->make(ProfileEvent::class, [$profile]); @@ -175,7 +183,8 @@ class SettingsController extends Controller throw new NotFoundHttpException(); } return $this->render( - 'privacy', [ + 'privacy', + [ 'module' => $this->module ] ); @@ -196,9 +205,9 @@ class SettingsController extends Controller throw new NotFoundHttpException(); } /** - * * - * @var GdprDeleteForm $form + * + * @var GdprDeleteForm $form */ $form = $this->make(GdprDeleteForm::class); @@ -249,7 +258,8 @@ class SettingsController extends Controller } return $this->render( - 'gdpr-delete', [ + 'gdpr-delete', + [ 'model' => $form, ] ); @@ -258,9 +268,9 @@ class SettingsController extends Controller public function actionGdprConsent() { /** - * * - * @var User $user + * + * @var User $user */ $user = Yii::$app->user->identity; if ($user->gdpr_consent) { @@ -270,7 +280,9 @@ class SettingsController extends Controller $model->addRule('gdpr_consent', 'boolean'); $model->addRule('gdpr_consent', 'default', ['value' => 0, 'skipOnEmpty' => false]); $model->addRule( - 'gdpr_consent', 'compare', [ + 'gdpr_consent', + 'compare', + [ 'compareValue' => true, 'message' => Yii::t('usuario', 'Your consent is required to work with this site'), 'when' => function () { @@ -289,7 +301,8 @@ class SettingsController extends Controller } return $this->render( - 'gdpr-consent', [ + 'gdpr-consent', + [ 'model' => $model, 'gdpr_consent_hint' => $this->module->getConsentMessage(), ] @@ -345,9 +358,9 @@ class SettingsController extends Controller public function actionAccount() { /** -* +* * - * @var SettingsForm $form + * @var SettingsForm $form */ $form = $this->make(SettingsForm::class); $event = $this->make(UserEvent::class, [$form->getUser()]); @@ -416,9 +429,9 @@ class SettingsController extends Controller } /** - * * - * @var User $user + * + * @var User $user */ $user = Yii::$app->user->identity; $event = $this->make(UserEvent::class, [$user]); @@ -436,9 +449,9 @@ class SettingsController extends Controller public function actionTwoFactor($id) { /** - * * - * @var User $user + * + * @var User $user */ $user = $this->userQuery->whereId($id)->one(); @@ -456,9 +469,9 @@ class SettingsController extends Controller Yii::$app->response->format = Response::FORMAT_JSON; /** - * * - * @var User $user + * + * @var User $user */ $user = $this->userQuery->whereId($id)->one(); @@ -487,12 +500,12 @@ class SettingsController extends Controller public function actionTwoFactorDisable($id) { /** - * * - * @var User $user + * + * @var User $user */ $user = $this->userQuery->whereId($id)->one(); - + if (null === $user) { throw new NotFoundHttpException(); } @@ -511,7 +524,33 @@ class SettingsController extends Controller } /** - * @param $id + * Display list session history. + */ + public function actionSessionHistory() + { + $searchModel = new SessionHistorySearch([ + 'user_id' => Yii::$app->user->id, + ]); + $dataProvider = $searchModel->search(Yii::$app->request->queryParams); + + return $this->render('session-history', [ + 'searchModel' => $searchModel, + 'dataProvider' => $dataProvider, + ]); + } + + /** + * Terminate all session user + */ + public function actionTerminateSessions() + { + $this->make(TerminateUserSessionsService::class, [Yii::$app->user->id])->run(); + + return $this->redirect(['session-history']); + } + + /** + * @param $id * @throws ForbiddenHttpException * @throws NotFoundHttpException * @throws \Exception @@ -521,9 +560,9 @@ class SettingsController extends Controller protected function disconnectSocialNetwork($id) { /** - * * - * @var SocialNetworkAccount $account + * + * @var SocialNetworkAccount $account */ $account = $this->socialNetworkAccountQuery->whereId($id)->one(); diff --git a/src/User/Event/SessionEvent.php b/src/User/Event/SessionEvent.php new file mode 100755 index 0000000..196d8e1 --- /dev/null +++ b/src/User/Event/SessionEvent.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Event; + +use Da\User\Model\User; +use yii\base\Event; + +/** + * @property-read User $user + */ +class SessionEvent extends Event +{ + const EVENT_BEFORE_TERMINATE_USER_SESSIONS = 'beforeTerminateUserSessions'; + const EVENT_AFTER_TERMINATE_USER_SESSIONS = 'afterTerminateUserSessions'; + + protected $user; + + public function __construct(User $user, array $config = []) + { + $this->user = $user; + parent::__construct($config); + } + + public function getUser() + { + return $this->user; + } +} diff --git a/src/User/Event/UserEvent.php b/src/User/Event/UserEvent.php index 948c0bb..249fbe8 100644 --- a/src/User/Event/UserEvent.php +++ b/src/User/Event/UserEvent.php @@ -23,8 +23,8 @@ class UserEvent extends Event const EVENT_AFTER_CREATE = 'afterCreate'; const EVENT_BEFORE_DELETE = 'beforeDelete'; const EVENT_AFTER_DELETE = 'afterDelete'; - const EVENT_BEFORE_REGISTER = 'beforeRegister'; - const EVENT_AFTER_REGISTER = 'afterRegister'; + const EVENT_BEFORE_REGISTER = 'beforeRegistration'; + const EVENT_AFTER_REGISTER = 'afterRegistration'; const EVENT_BEFORE_ACCOUNT_UPDATE = 'beforeAccountUpdate'; const EVENT_AFTER_ACCOUNT_UPDATE = 'afterAccountUpdate'; const EVENT_BEFORE_PROFILE_UPDATE = 'beforeProfileUpdate'; diff --git a/src/User/Filter/AccessRuleFilter.php b/src/User/Filter/AccessRuleFilter.php index b32721f..cb65826 100644 --- a/src/User/Filter/AccessRuleFilter.php +++ b/src/User/Filter/AccessRuleFilter.php @@ -37,7 +37,7 @@ class AccessRuleFilter extends AccessRule /** @var User $identity */ $identity = $user->identity; if (!$identity->gdpr_consent) { - Yii::$app->response->redirect([ "/$consentAction"])->send(); + Yii::$app->response->redirect(["/{$consentAction}"])->send(); } } } diff --git a/src/User/Helper/SecurityHelper.php b/src/User/Helper/SecurityHelper.php index 5fec4ab..372ec5b 100644 --- a/src/User/Helper/SecurityHelper.php +++ b/src/User/Helper/SecurityHelper.php @@ -13,8 +13,8 @@ namespace Da\User\Helper; use Yii; use yii\base\Exception; -use yii\base\Security; use yii\base\InvalidConfigException; +use yii\base\Security; class SecurityHelper { @@ -76,8 +76,7 @@ class SecurityHelper if (!isset($minPasswordRequirements)) { if (isset(Yii::$app->getModule('user')->minPasswordRequirements)) { $minPasswordRequirements = Yii::$app->getModule('user')->minPasswordRequirements; - } - else { + } else { $minPasswordRequirements = [ 'lower' => 1, 'digit' => 1, diff --git a/src/User/Migration/Session/m000000_000001_create_session_history_table.php b/src/User/Migration/Session/m000000_000001_create_session_history_table.php new file mode 100755 index 0000000..a33ccad --- /dev/null +++ b/src/User/Migration/Session/m000000_000001_create_session_history_table.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Migration\Session; + +use Da\User\Helper\MigrationHelper; +use yii\db\Migration; + + +class m000000_000001_create_session_history_table extends Migration +{ + const SESSION_HISTORY_TABLE = '{{%session_history}}'; + const USER_TABLE = '{{%user}}'; + + /** + * {@inheritdoc} + */ + public function safeUp() + { + $this->createTable(self::SESSION_HISTORY_TABLE, [ + 'user_id' => $this->integer(), + 'session_id' => $this->string()->null(), + 'user_agent' => $this->string()->notNull(), + 'ip' => $this->string(45)->notNull(), + 'created_at' => $this->integer()->notNull(), + 'updated_at' => $this->integer()->notNull(), + ]); + + $this->createIndex( + '{{%session_history_user_id}}', + self::SESSION_HISTORY_TABLE, + ['user_id'] + ); + + $this->createIndex( + '{{%session_history_session_id}}', + self::SESSION_HISTORY_TABLE, + ['session_id'] + ); + + $this->createIndex( + '{{%session_history_updated_at}}', + self::SESSION_HISTORY_TABLE, + ['updated_at'] + ); + + $this->addForeignKey( + '{{%fk_user_session_history}}', + self::SESSION_HISTORY_TABLE, + 'user_id', + self::USER_TABLE, + 'id', + 'CASCADE', + MigrationHelper::isMicrosoftSQLServer($this->db->driverName) ? 'NO ACTION' : 'RESTRICT' + ); + } + + /** + * {@inheritdoc} + */ + public function safeDown() + { + $this->dropTable(self::SESSION_HISTORY_TABLE); + } +} diff --git a/src/User/Model/AbstractAuthItem.php b/src/User/Model/AbstractAuthItem.php index b550b10..aee8d6e 100644 --- a/src/User/Model/AbstractAuthItem.php +++ b/src/User/Model/AbstractAuthItem.php @@ -97,7 +97,7 @@ abstract class AbstractAuthItem extends Model return [ ['itemName', 'safe'], ['name', 'required'], - ['name', 'match', 'pattern' => '/^\w[\w.:\-]+\w$/'], + ['name', 'match', 'pattern' => '/^\w[\w.:\-]+\w$/u'], [['name', 'description', 'rule'], 'trim'], [ 'name', diff --git a/src/User/Model/Profile.php b/src/User/Model/Profile.php index 72c1450..7d00e91 100644 --- a/src/User/Model/Profile.php +++ b/src/User/Model/Profile.php @@ -25,7 +25,7 @@ use yii\base\InvalidParamException; use yii\db\ActiveRecord; /** - * @property int $user_id + * @property int $user_id * @property string $name * @property string $public_email * @property string $gravatar_email @@ -34,7 +34,7 @@ use yii\db\ActiveRecord; * @property string $website * @property string $bio * @property string $timezone - * @property User $user + * @property User $user */ class Profile extends ActiveRecord { diff --git a/src/User/Model/SessionHistory.php b/src/User/Model/SessionHistory.php new file mode 100755 index 0000000..4331e55 --- /dev/null +++ b/src/User/Model/SessionHistory.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Model; + +use Da\User\Module; +use Da\User\Query\SessionHistoryQuery; +use Da\User\Traits\ModuleAwareTrait; +use Yii; +use yii\behaviors\TimestampBehavior; +use yii\db\ActiveRecord; +use yii\db\ActiveQuery; + +/** + * @property int $user_id + * @property string $session_id + * @property string $user_agent + * @property string $ip + * @property int $created_at + * @property int $updated_at + * + * @property User $user + * @property bool $isActive + * + * Dependencies: + * @property-read Module $module + */ +class SessionHistory extends ActiveRecord +{ + use ModuleAwareTrait; + + /** + * {@inheritdoc} + */ + public static function tableName() + { + return '{{%session_history}}'; + } + + /** @inheritdoc */ + public function behaviors() + { + return [ + [ + 'class' => TimestampBehavior::class, + 'updatedAtAttribute' => false, + ] + ]; + } + + /** + * {@inheritdoc} + */ + public function attributeLabels() + { + return [ + 'user_id' => Yii::t('usuario', 'User ID'), + 'session_id' => Yii::t('usuario', 'Session ID'), + 'user_agent' => Yii::t('usuario', 'User agent'), + 'ip' => Yii::t('usuario', 'IP'), + 'created_at' => Yii::t('usuario', 'Created at'), + 'updated_at' => Yii::t('usuario', 'Last activity'), + ]; + } + + /** + * @return bool Whether the session is an active or not. + */ + public function getIsActive() + { + return isset($this->session_id) && $this->updated_at + $this->getModule()->rememberLoginLifespan > time(); + } + + /** + * @return ActiveQuery + */ + public function getUser() + { + return $this->hasOne($this->module->classMap['User'], ['id' => 'user_id']); + } + + /** @inheritdoc */ + public function beforeSave($insert) + { + if ($insert && empty($this->session_id)) { + $this->setAttribute('session_id', Yii::$app->session->getId()); + } + + return parent::beforeSave($insert); + } + + /** @inheritdoc */ + public static function primaryKey() + { + return ['user_id', 'session_id']; + } + + public static function find() + { + return new SessionHistoryQuery(static::class); + } +} diff --git a/src/User/Model/SocialNetworkAccount.php b/src/User/Model/SocialNetworkAccount.php index 3251880..e076327 100644 --- a/src/User/Model/SocialNetworkAccount.php +++ b/src/User/Model/SocialNetworkAccount.php @@ -22,17 +22,17 @@ use yii\helpers\Url; /** * /** - * @property int $id Id - * @property int $user_id User id, null if account is not bind to user - * @property string $provider Name of service - * @property string $client_id Account id - * @property string $data Account properties returned by social network (json encoded) - * @property string $decodedData Json-decoded properties + * @property int $id Id + * @property int $user_id User id, null if account is not bind to user + * @property string $provider Name of service + * @property string $client_id Account id + * @property string $data Account properties returned by social network (json encoded) + * @property string $decodedData Json-decoded properties * @property string $code * @property string $email * @property string $username - * @property int $created_at - * @property User $user User that this account is connected for + * @property int $created_at + * @property User $user User that this account is connected for */ class SocialNetworkAccount extends ActiveRecord { diff --git a/src/User/Model/Token.php b/src/User/Model/Token.php index 2ee8e97..54c4abd 100644 --- a/src/User/Model/Token.php +++ b/src/User/Model/Token.php @@ -24,13 +24,13 @@ use yii\helpers\Url; /** * Token Active Record model. * - * @property int $user_id + * @property int $user_id * @property string $code - * @property int $type + * @property int $type * @property string $url - * @property bool $isExpired - * @property int $created_at - * @property User $user + * @property bool $isExpired + * @property int $created_at + * @property User $user */ class Token extends ActiveRecord { diff --git a/src/User/Model/User.php b/src/User/Model/User.php index 3671c93..eb30c83 100644 --- a/src/User/Model/User.php +++ b/src/User/Model/User.php @@ -31,33 +31,33 @@ use yii\web\IdentityInterface; * * @property bool $isAdmin * @property bool $isBlocked - * @property bool $isConfirmed whether user account has been confirmed or not - * @property bool $gdpr_deleted whether user requested deletion of his account - * @property bool $gdpr_consent whether user has consent personal data processing + * @property bool $isConfirmed whether user account has been confirmed or not + * @property bool $gdpr_deleted whether user requested deletion of his account + * @property bool $gdpr_consent whether user has consent personal data processing * * Database fields: - * @property int $id - * @property string $username - * @property string $email - * @property string $unconfirmed_email - * @property string $password_hash - * @property string $auth_key - * @property string $auth_tf_key - * @property int $auth_tf_enabled - * @property string $registration_ip - * @property int $confirmed_at - * @property int $blocked_at - * @property int $flags - * @property int $created_at - * @property int $updated_at - * @property int $last_login_at - * @property int $gdpr_consent_date date of agreement of data processing - * @property string $last_login_ip - * @property int $password_changed_at - * @property int $password_age - * Defined relations: + * @property int $id + * @property string $username + * @property string $email + * @property string $unconfirmed_email + * @property string $password_hash + * @property string $auth_key + * @property string $auth_tf_key + * @property int $auth_tf_enabled + * @property string $registration_ip + * @property int $confirmed_at + * @property int $blocked_at + * @property int $flags + * @property int $created_at + * @property int $updated_at + * @property int $last_login_at + * @property int $gdpr_consent_date date of agreement of data processing + * @property string $last_login_ip + * @property int $password_changed_at + * @property int $password_age + * Defined relations: * @property SocialNetworkAccount[] $socialNetworkAccounts - * @property Profile $profile + * @property Profile $profile */ class User extends ActiveRecord implements IdentityInterface { diff --git a/src/User/Module.php b/src/User/Module.php old mode 100644 new mode 100755 index 05af05e..1212d13 --- a/src/User/Module.php +++ b/src/User/Module.php @@ -22,6 +22,21 @@ use yii\helpers\Html; */ class Module extends BaseModule { + /** + * @var bool Enable the 'session history' function + * Using with {@see SessionHistoryDecorator} + */ + public $enableSessionHistory = false; + /** + * @var int|bool The number of 'session history' records will be stored for user + * if equals false records will not be deleted + */ + public $numberSessionHistory = false; + /** + * @var int|bool The time after which the expired 'session history' will be deleted + * if equals false records will not be deleted + */ + public $timeoutSessionHistory = false; /** * @var bool whether to enable european G.D.P.R. compliance. * This will add a few elements to comply with european general data protection regulation. @@ -214,11 +229,11 @@ class Module extends BaseModule * @var boolean whether to disable IP logging into user table */ public $disableIpLogging = false; - + /** * @var array Minimum requirements when a new password is automatically generated. - * Array structure: `requirement => minimum number characters`. - * + * Array structure: `requirement => minimum number characters`. + * * Possible array keys: * - lower: minimum number of lowercase characters; * - upper: minimum number of uppercase characters; @@ -251,4 +266,20 @@ class Module extends BaseModule return $this->gdprConsentMessage ?: $defaultConsentMessage; } + + /** + * @return bool + */ + public function hasNumberSessionHistory() + { + return $this->numberSessionHistory !== false && $this->numberSessionHistory > 0; + } + + /** + * @return bool + */ + public function hasTimeoutSessionHistory() + { + return $this->timeoutSessionHistory !== false && $this->timeoutSessionHistory > 0; + } } diff --git a/src/User/Query/SessionHistoryCondition.php b/src/User/Query/SessionHistoryCondition.php new file mode 100755 index 0000000..c774c66 --- /dev/null +++ b/src/User/Query/SessionHistoryCondition.php @@ -0,0 +1,158 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Query; + +use Da\User\Traits\ModuleAwareTrait; +use yii\web\Session; +use Yii; + +class SessionHistoryCondition +{ + use ModuleAwareTrait; + + private $session; + + public function __construct(Session $session) + { + $this->session = $session; + } + + public function unbindSession() + { + return ['session_id' => null]; + } + + public function bySession($sessionId) + { + return ['session_id' => $sessionId]; + } + + public function byUser($userId) + { + return [ + 'user_id' => $userId, + ]; + } + + public function byUserSession($userId, $sessionId) + { + return [ + 'user_id' => $userId, + 'session_id' => $sessionId, + ]; + } + + public function inactive($userId = null) + { + $where = [ + 'AND', + ['session_id' => null] + ]; + + if (isset($userId)) { + $where[] = $this->byUser($userId); + } + + return $where; + } + + public function expired($userId = null) + { + $where = [ + 'AND', + ['<', 'updated_at', $this->getExpiredTime()] + ]; + + if (isset($userId)) { + $where[] = $this->byUser($userId); + } + + return $where; + } + + public function expiredInactive($userId = null) + { + return [ + 'OR', + $this->expired($userId), + $this->inactive($userId), + ]; + } + + public function shouldDeleteBefore($updatedAt, $userId) + { + $condition = ['<', 'updated_at', $updatedAt]; + if ($updatedAt > $this->getExpiredTime()) { + $condition = [ + 'OR', + [ + 'AND', + $this->inactive(), + $condition, + ], + $this->expired() + ]; + } + + return [ + 'AND', + $this->byUser($userId), + $condition, + ]; + } + + /** + * @return int + */ + public function getExpiredTime() + { + $module = $this->getModule(); + $time = time() - max($module->rememberLoginLifespan, $this->session->getTimeout()); + if (false === $module->hasTimeoutSessionHistory()) { + return $time; + } + + return $time - $module->timeoutSessionHistory; + } + + public function inactiveData() + { + return [ + 'session_id' => null, + ]; + } + + /** + * @return array + */ + public function currentUserData() + { + return [ + 'user_id' => Yii::$app->user->id, + 'session_id' => Yii::$app->session->getId(), + 'user_agent' => Yii::$app->request->userAgent, + 'ip' => Yii::$app->request->userIP, + ]; + } + + /** + * @return array + */ + public function currentUserCondition() + { + return [ + 'user_id' => Yii::$app->user->id, + 'session_id' => Yii::$app->session->getId(), + 'user_agent' => Yii::$app->request->userAgent, + ]; + } +} diff --git a/src/User/Query/SessionHistoryQuery.php b/src/User/Query/SessionHistoryQuery.php new file mode 100755 index 0000000..d8ad71c --- /dev/null +++ b/src/User/Query/SessionHistoryQuery.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Query; + +use Da\User\Traits\ModuleAwareTrait; +use yii\db\ActiveQuery; +use Yii; + +class SessionHistoryQuery extends ActiveQuery +{ + use ModuleAwareTrait; + + public function whereUserId($userId) + { + return $this->andWhere($this->getCondition()->byUser($userId)); + } + + public function whereActive() + { + return $this->andWhere(['IS NOT', 'session_id', null]); + } + + public function whereInActive($userId) + { + return $this->andWhere($this->getCondition()->inactive($userId)); + } + + + public function whereExpired($userId) + { + return $this->andWhere($this->getCondition()->expired($userId)); + } + + public function whereExpiredInActive($userId) + { + return $this->andWhere($this->getCondition()->expiredInactive($userId)); + } + + public function selectSessionId() + { + return $this->select(['session_id']); + } + + public function whereUserSession($userId, $sessionId) + { + return $this->andWhere($this->getCondition()->byUserSession( + $userId, + $sessionId + )); + } + + public function whereCurrentUser() + { + return $this->andWhere($this->getCondition()->currentUserCondition()); + } + + public function oldestUpdatedTimeActiveSession($userId) + { + return $this->whereExpiredInActive($userId) + ->select(['updated_at']) + ->limit(1) + ->offset($this->getModule()->numberSessionHistory) + ->orderBy(['updated_at' => SORT_DESC])->scalar(); + } + + /** + * @return SessionHistoryCondition + */ + protected function getCondition() + { + return Yii::$container->get(SessionHistoryCondition::class); + } +} diff --git a/src/User/Search/SessionHistorySearch.php b/src/User/Search/SessionHistorySearch.php new file mode 100755 index 0000000..2775652 --- /dev/null +++ b/src/User/Search/SessionHistorySearch.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Search; + +use Da\User\Model\SessionHistory; +use Da\User\Traits\ContainerAwareTrait; +use yii\base\InvalidConfigException; +use yii\base\InvalidParamException; +use yii\data\ActiveDataProvider; + + +class SessionHistorySearch extends SessionHistory +{ + use ContainerAwareTrait; + + /** + * {@inheritdoc} + */ + public function rules() + { + return [ + [['user_agent', 'ip'], 'safe'], + ]; + } + + /** + * @param array $params + * + * @throws InvalidConfigException + * @throws InvalidParamException + * + * @return ActiveDataProvider + */ + public function search($params) + { + $query = SessionHistory::find()->andWhere([ + 'user_id' => $this->user_id, + ]); + + /** @var ActiveDataProvider $dataProvider */ + $dataProvider = $this->make( + ActiveDataProvider::class, + [], + [ + 'query' => $query, + 'sort' => [ + 'defaultOrder' => [ + 'updated_at' => SORT_DESC + ], + ] + ] + ); + + $this->load($params); + + if (!$this->validate()) { + return $dataProvider; + } + + $query->andFilterWhere(['like', 'user_agent', $this->user_agent]) + ->andFilterWhere(['like', 'ip', $this->ip]); + + return $dataProvider; + } +} diff --git a/src/User/Service/SessionHistory/DBTerminateSessionsService.php b/src/User/Service/SessionHistory/DBTerminateSessionsService.php new file mode 100755 index 0000000..f494c5c --- /dev/null +++ b/src/User/Service/SessionHistory/DBTerminateSessionsService.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Service\SessionHistory; + + +use yii\web\DbSession; + +class DBTerminateSessionsService implements TerminateSessionsServiceInterface +{ + protected $sessionIds; + protected $dbSession; + protected $fieldName; + + public function __construct(array $sessionIds, DbSession $dbSession, $fieldName = 'id') + { + $this->sessionIds = $sessionIds; + $this->dbSession = $dbSession; + $this->fieldName = $fieldName; + } + + public function run() + { + if (in_array(session_id(), $this->sessionIds)) { + session_write_close(); + } + + $this->dbSession->db->createCommand()->delete( + $this->dbSession->sessionTable, + [$this->fieldName => $this->sessionIds] + )->execute(); + + return true; + } +} diff --git a/src/User/Service/SessionHistory/SessionHistoryDecorator.php b/src/User/Service/SessionHistory/SessionHistoryDecorator.php new file mode 100755 index 0000000..a1c0032 --- /dev/null +++ b/src/User/Service/SessionHistory/SessionHistoryDecorator.php @@ -0,0 +1,461 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Service\SessionHistory; + +use Da\User\Model\SessionHistory; +use Da\User\Query\SessionHistoryCondition; +use Da\User\Query\SessionHistoryQuery; +use Da\User\Traits\ModuleAwareTrait; +use Yii; +use yii\db\Exception; +use yii\web\Session; +use yii\base\InvalidArgumentException as BaseInvalidArgumentException; + +/** + * Decorator for the {@see Session} class for storing the 'session history' + * + * Not decorated methods: + * {@see Session::open()} + * {@see Session::close()} + * {@see Session::destroy()} + * {@see Session::get()} + * {@see Session::set()} + */ +class SessionHistoryDecorator extends Session +{ + use ModuleAwareTrait; + + public $sessionHistoryTable = '{{%session_history}}'; + + /** + * @var Session + */ + public $session; + + public $condition; + + public function __construct( + Session $session, + SessionHistoryCondition $historyCondition, + $config = [] + ) { + $this->session = $session; + $this->condition = $historyCondition; + + parent::__construct($config); + } + + /** @inheritdoc */ + public function getUseCustomStorage() + { + return $this->session->getUseCustomStorage(); + } + + /** @inheritdoc */ + public function getIsActive() + { + return $this->session->getIsActive(); + } + + /** @inheritdoc */ + public function getHasSessionId() + { + return $this->session->getHasSessionId(); + } + + /** @inheritdoc */ + public function setHasSessionId($value) + { + return $this->session->setHasSessionId($value); + } + + /** @inheritdoc */ + public function getId() + { + return $this->session->getId(); + } + + /** @inheritdoc */ + public function setId($value) + { + return $this->session->setId($value); + } + + /** @inheritdoc */ + public function regenerateID($deleteOldSession = false) + { + return $this->getDb()->transaction(function () use ($deleteOldSession) { + $oldSid = session_id(); + if (false === $this->session->regenerateID($deleteOldSession)) { + return false; + } + + if (false === $this->getModule()->enableSessionHistory) { + return true; + } + + $user = Yii::$app->user; + if ($user->getIsGuest()) { + $this->unbindSessionHistory($oldSid); + } else { + $this->getDB()->createCommand() + ->delete( + $this->sessionHistoryTable, + $this->condition->byUserSession($user->getId(), $oldSid) + )->execute(); + } + + return true; + }); + } + + /** @inheritdoc */ + public function getName() + { + return $this->session->getName(); + } + + /** @inheritdoc */ + public function setName($value) + { + return $this->session->setName($value); + } + + /** @inheritdoc */ + public function getSavePath() + { + return $this->session->getSavePath(); + } + + /** @inheritdoc */ + public function setSavePath($value) + { + return $this->session->setSavePath($value); + } + + /** @inheritdoc */ + public function getCookieParams() + { + return $this->session->getCookieParams(); + } + + /** @inheritdoc */ + public function setCookieParams(array $value) + { + return $this->session->setCookieParams($value); + } + + /** @inheritdoc */ + public function getUseCookies() + { + return $this->session->getUseCookies(); + } + + /** @inheritdoc */ + public function setUseCookies($value) + { + return $this->session->setUseCookies($value); + } + + /** @inheritdoc */ + public function getGCProbability() + { + return $this->session->getGCProbability(); + } + + /** @inheritdoc */ + public function setGCProbability($value) + { + return $this->session->setGCProbability($value); + } + + /** @inheritdoc */ + public function getUseTransparentSessionID() + { + return $this->session->getUseTransparentSessionID(); + } + + /** @inheritdoc */ + public function setUseTransparentSessionID($value) + { + return $this->session->setUseTransparentSessionID($value); + } + + /** @inheritdoc */ + public function getTimeout() + { + return $this->session->getTimeout(); + } + + /** @inheritdoc */ + public function setTimeout($value) + { + return $this->session->setTimeout($value); + } + + /** @inheritdoc */ + public function openSession($savePath, $sessionName) + { + return $this->session->openSession($savePath, $sessionName); + } + + /** @inheritdoc */ + public function closeSession() + { + return $this->session->closeSession(); + } + + /** @inheritdoc */ + public function readSession($id) + { + return $this->session->readSession($id); + } + + /** @inheritdoc */ + public function writeSession($id, $data) + { + return $this->session->writeSession($id, $data) && + ( + false === $this->getModule()->enableSessionHistory || + $this->getDb()->transaction(function () use ($id, $data) { + if (Yii::$app->user->getIsGuest()) { + return true; + } + + $updatedAt = ['updated_at' => time()]; + + $model = $this->getHistoryQuery() + ->whereCurrentUser() + ->one(); + if (isset($model)) { + $model->updateAttributes($updatedAt); + $result = true; + } else { + $model = Yii::createObject([ + 'class' => SessionHistory::class, + ] + $this->condition->currentUserData() + $updatedAt); + if (!$result = $model->save()) { + throw new BaseInvalidArgumentException( + print_r($model->errors, 1) + ); + } + + $this->displacementHistory($model->user_id); + } + + return $result; + }) + ); + + } + + /** @inheritdoc */ + public function destroySession($id) + { + return $this->session->destroySession($id) && + ( + false === $this->getModule()->enableSessionHistory || + $this->getDb()->transaction(function () use ($id) { + $this->unbindSessionHistory($id); + + return true; + }) + ); + } + + /** @inheritdoc */ + public function gcSession($maxLifetime) + { + return $this->session->gcSession($maxLifetime) && + ( + false === $this->getModule()->enableSessionHistory || + $this->getDb()->transaction(function () use ($maxLifetime) { + $this->getDb()->createCommand()->update( + $this->sessionHistoryTable, + $this->condition->inactiveData(), + $this->condition->expired() + )->execute(); + return true; + }) + ); + } + + /** @inheritdoc */ + public function getIterator() + { + return $this->session->getIterator(); + } + + /** @inheritdoc */ + public function getCount() + { + return $this->session->getCount(); + } + + /** @inheritdoc */ + public function count() + { + return $this->session->count(); + } + + /** @inheritdoc */ + public function remove($key) + { + return $this->session->remove($key); + } + + /** @inheritdoc */ + public function removeAll() + { + return $this->session->removeAll(); + } + + /** @inheritdoc */ + public function has($key) + { + return $this->session->has($key); + } + + /** @inheritdoc */ + public function getFlash($key, $defaultValue = null, $delete = false) + { + return $this->session->getFlash($key, $defaultValue, $delete); + } + + /** @inheritdoc */ + public function getAllFlashes($delete = false) + { + return $this->session->getAllFlashes($delete); + } + + /** @inheritdoc */ + public function setFlash($key, $value = true, $removeAfterAccess = true) + { + return $this->session->setFlash($key, $value, $removeAfterAccess); + } + + /** @inheritdoc */ + public function addFlash($key, $value = true, $removeAfterAccess = true) + { + return $this->session->addFlash($key, $value, $removeAfterAccess); + } + + /** @inheritdoc */ + public function removeFlash($key) + { + return $this->session->removeFlash($key); + } + + /** @inheritdoc */ + public function removeAllFlashes() + { + return $this->session->removeAllFlashes(); + } + + /** @inheritdoc */ + public function hasFlash($key) + { + return $this->session->hasFlash($key); + } + + /** @inheritdoc */ + public function offsetExists($offset) + { + return $this->session->offsetExists($offset); + } + + /** @inheritdoc */ + public function offsetGet($offset) + { + return $this->session->offsetGet($offset); + } + + /** @inheritdoc */ + public function offsetSet($offset, $item) + { + return $this->session->offsetSet($offset, $item); + } + + /** @inheritdoc */ + public function offsetUnset($offset) + { + return $this->session->offsetUnset($offset); + } + + /** @inheritdoc */ + public function setCacheLimiter($cacheLimiter) + { + return $this->session->setCacheLimiter($cacheLimiter); + } + + /** @inheritdoc */ + public function getCacheLimiter() + { + return $this->session->getCacheLimiter(); + } + + /** + * @param string $id + * @return bool + * @throws Exception + */ + protected function unbindSessionHistory($id) + { + return (bool)$this->getDb()->createCommand()->update( + $this->sessionHistoryTable, + $this->condition->unbindSession(), + $this->condition->bySession($id) + )->execute(); + } + + /** + * + * @param int $userId + * @return bool + * @throws Exception + */ + protected function displacementHistory($userId) + { + $module = $this->getModule(); + + if (false === $module->hasNumberSessionHistory()) { + return true; + } + + $updatedAt = $this->getHistoryQuery() + ->oldestUpdatedTimeActiveSession($userId); + + if (!$updatedAt) { + return true; + } + + $this->getDB()->createCommand()->delete( + $this->sessionHistoryTable, + $this->condition->shouldDeleteBefore(intval($updatedAt), $userId) + )->execute(); + + return true; + } + + /** + * @return SessionHistoryQuery + */ + protected function getHistoryQuery() + { + return Yii::$container->get(SessionHistoryQuery::class); + } + + protected function getDb() + { + return Yii::$app->getDb(); + } +} diff --git a/src/User/Service/SessionHistory/TerminateSessionsService.php b/src/User/Service/SessionHistory/TerminateSessionsService.php new file mode 100755 index 0000000..ae4aaad --- /dev/null +++ b/src/User/Service/SessionHistory/TerminateSessionsService.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Service\SessionHistory; + + +class TerminateSessionsService implements TerminateSessionsServiceInterface +{ + protected $sessionIds; + + public function __construct(array $sessionIds) + { + $this->sessionIds = $sessionIds; + } + + public function run() + { + $currentSessionId = session_id(); + if (session_status() === PHP_SESSION_ACTIVE) { + session_write_close(); + } + + foreach ($this->sessionIds as $sessionId) { + if ($sessionId === $currentSessionId) { + $currentSessionId = null; + } + + session_id($sessionId); + session_start(); + session_destroy(); + } + + if ($currentSessionId) { + session_id($currentSessionId); + } + session_start(); + + return true; + } +} diff --git a/src/User/Service/SessionHistory/TerminateSessionsServiceInterface.php b/src/User/Service/SessionHistory/TerminateSessionsServiceInterface.php new file mode 100755 index 0000000..35d4dfa --- /dev/null +++ b/src/User/Service/SessionHistory/TerminateSessionsServiceInterface.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Service\SessionHistory; + + +use Da\User\Contracts\ServiceInterface; + +interface TerminateSessionsServiceInterface extends ServiceInterface +{ +} diff --git a/src/User/Service/SessionHistory/TerminateUserSessionsService.php b/src/User/Service/SessionHistory/TerminateUserSessionsService.php new file mode 100755 index 0000000..377130a --- /dev/null +++ b/src/User/Service/SessionHistory/TerminateUserSessionsService.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Service\SessionHistory; + + +use Da\User\Contracts\ServiceInterface; +use Da\User\Event\SessionEvent; +use Da\User\Model\SessionHistory; +use Da\User\Model\User; +use Da\User\Traits\ContainerAwareTrait; +use Da\User\Traits\ModuleAwareTrait; +use yii\web\Session; +use Yii; + +class TerminateUserSessionsService implements ServiceInterface +{ + use ContainerAwareTrait; + use ModuleAwareTrait; + + protected $userId; + protected $session; + protected $excludeCurrentSession; + + public function __construct($userId, Session $session, $excludeCurrentSession = true) + { + $this->userId = intval($userId); + $this->session = $session; + $this->excludeCurrentSession = $excludeCurrentSession; + } + + public function run() + { + $user = $this->getUser($this->userId); + $sessionIds = $this->getSessionIds($user->id); + + Yii::$app->db->transaction(function () use ($sessionIds, $user) { + /** @var SessionEvent $event */ + $event = $this->make(SessionEvent::class, [$user]); + + $user->trigger(SessionEvent::EVENT_BEFORE_TERMINATE_USER_SESSIONS, $event); + + $this->make(TerminateSessionsServiceInterface::class, [$sessionIds])->run(); + + $user->updateAttributes([ + 'auth_key' => Yii::$app->security->generateRandomString(), + ]); + + if ($this->excludeCurrentUser()) { + Yii::$app->user->switchIdentity( + $user, + $this->getModule()->rememberLoginLifespan + ); + } + + $user->trigger(SessionEvent::EVENT_AFTER_TERMINATE_USER_SESSIONS, $event); + }); + + return true; + } + + /** + * @param int $userId + * @return User + */ + protected function getUser($userId) + { + return ($this->make(User::class))::findOne($userId); + } + + /** + * @param $userId + * @return int[] + */ + protected function getSessionIds($userId) + { + /** @var SessionHistory $sessionHistory */ + $sessionHistory = $this->make(SessionHistory::class); + $sessionIds = $sessionHistory::find()->whereUserId($userId)->whereActive()->selectSessionId()->column(); + + if ($this->excludeCurrentUser()) { + foreach ($sessionIds as $key => $sessionId) { + if ($sessionId === $this->session->id) { + unset($sessionIds[$key]); + break; + } + } + } + + return $sessionIds; + } + + protected function excludeCurrentUser() + { + return $this->excludeCurrentSession && $this->userId === Yii::$app->user->id; + } +} diff --git a/src/User/Service/UserConfirmationService.php b/src/User/Service/UserConfirmationService.php index aa18f4b..ab52ed4 100644 --- a/src/User/Service/UserConfirmationService.php +++ b/src/User/Service/UserConfirmationService.php @@ -19,7 +19,7 @@ use Da\User\Traits\MailAwareTrait; class UserConfirmationService implements ServiceInterface { use MailAwareTrait; - + protected $model; public function __construct(User $model) @@ -31,7 +31,7 @@ class UserConfirmationService implements ServiceInterface { $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()])) { $this->model->trigger(UserEvent::EVENT_AFTER_CONFIRMATION, $event); diff --git a/src/User/Widget/SessionStatusWidget.php b/src/User/Widget/SessionStatusWidget.php new file mode 100755 index 0000000..15bcfae --- /dev/null +++ b/src/User/Widget/SessionStatusWidget.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Da\User\Widget; + +use Da\User\Model\SessionHistory; +use Da\User\Traits\ContainerAwareTrait; +use Yii; +use yii\base\InvalidConfigException; +use yii\base\InvalidParamException; +use yii\base\Widget; +use yii\helpers\ArrayHelper; + +class SessionStatusWidget extends Widget +{ + use ContainerAwareTrait; + + /** + * @var SessionHistory + */ + public $model; + + /** + * {@inheritdoc} + * + * @throws InvalidConfigException + */ + public function init() + { + parent::init(); + if (!$this->model instanceof SessionHistory) { + throw new InvalidConfigException( + __CLASS__ . '::$userId should be instanceof ' . SessionHistory::class + ); + } + } + + /** + * {@inheritdoc} + * + * @throws InvalidParamException + */ + public function run() + { + if ($this->model->getIsActive()) { + if ($this->model->session_id === Yii::$app->session->id) { + $value = Yii::t('usuario', 'Current'); + } else { + $value = Yii::t('usuario', 'Active'); + } + } else { + $value = Yii::t('usuario', 'Inactive'); + } + + return $value; + } + + /** + * Returns available auth items to be attached to the user. + * + * @param int|null type of auth items or null to return all + * + * @return array + */ + protected function getAvailableItems($type = null) + { + return ArrayHelper::map( + $this->getAuthManager()->getItems($type), + 'name', + function ($item) { + return empty($item->description) + ? $item->name + : $item->name . ' (' . $item->description . ')'; + } + ); + } +} diff --git a/src/User/resources/i18n/ca/usuario.php b/src/User/resources/i18n/ca/usuario.php index 59af1ed..85cb688 100644 --- a/src/User/resources/i18n/ca/usuario.php +++ b/src/User/resources/i18n/ca/usuario.php @@ -28,6 +28,7 @@ return [ 'Account details' => '', 'Account details have been updated' => '', 'Account settings' => '', + 'Active' => '', 'Already registered? Sign in!' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'An error occurred processing your request' => '', @@ -81,6 +82,7 @@ return [ 'Create new rule' => '', 'Created at' => '', 'Credentials will be sent to the user by email' => '', + 'Current' => '', 'Current password' => '', 'Current password is not valid' => '', 'Data privacy' => '', @@ -113,13 +115,16 @@ return [ 'Hello' => '', 'Here you can download your personal data in a comma separated values format.' => '', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', + 'IP' => '', 'If you already registered, sign in and connect this account on settings page' => '', 'If you cannot click the link, please try pasting the text into your browser' => '', 'If you did not make this request you can ignore this email' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Impersonate this user' => '', 'In order to complete your registration, please click the link below' => '', 'In order to complete your request, please click the link below' => '', 'In order to finish your registration, we need you to enter following fields' => '', + 'Inactive' => '', 'Information' => '', 'Invalid login or password' => '', 'Invalid or expired link' => '', @@ -129,6 +134,7 @@ return [ 'It will be deleted forever' => '', 'Items' => '', 'Joined on {0, date}' => '', + 'Last activity' => '', 'Last login IP' => '', 'Last login time' => '', 'Last password change' => '', @@ -187,11 +193,15 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => '', 'Select rule...' => '', 'Send password recovery email' => '', + 'Session ID' => '', + 'Session history' => '', 'Sign in' => '', 'Sign up' => '', 'Something went wrong' => '', + 'Status' => '', 'Submit' => '', 'Switch identities is disabled.' => '', + 'Terminate all sessions' => '', 'Thank you for signing up on {0}' => '', 'Thank you, registration is now complete.' => '', 'The "recaptcha" component must be configured.' => '', @@ -233,7 +243,9 @@ return [ 'Update rule' => '', 'Update user account' => '', 'Updated at' => '', + 'User ID' => '', 'User account could not be created.' => '', + 'User agent' => '', 'User block status has been updated.' => '', 'User could not be registered.' => '', 'User has been confirmed' => '', @@ -259,6 +271,7 @@ return [ 'You can connect multiple accounts to be able to log in using them' => '', 'You cannot remove your own account' => '', 'You need to confirm your email address' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your account details have been updated' => '', 'Your account has been blocked' => '', 'Your account has been blocked.' => '', @@ -279,6 +292,4 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', '{0} cannot be blank.' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/da/usuario.php b/src/User/resources/i18n/da/usuario.php index 59af1ed..4aff8ed 100644 --- a/src/User/resources/i18n/da/usuario.php +++ b/src/User/resources/i18n/da/usuario.php @@ -28,6 +28,7 @@ return [ 'Account details' => '', 'Account details have been updated' => '', 'Account settings' => '', + 'Active' => '', 'Already registered? Sign in!' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'An error occurred processing your request' => '', @@ -81,6 +82,7 @@ return [ 'Create new rule' => '', 'Created at' => '', 'Credentials will be sent to the user by email' => '', + 'Current' => '', 'Current password' => '', 'Current password is not valid' => '', 'Data privacy' => '', @@ -112,14 +114,17 @@ return [ 'Gravatar email' => '', 'Hello' => '', 'Here you can download your personal data in a comma separated values format.' => '', + 'IP' => '', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', 'If you already registered, sign in and connect this account on settings page' => '', 'If you cannot click the link, please try pasting the text into your browser' => '', 'If you did not make this request you can ignore this email' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Impersonate this user' => '', 'In order to complete your registration, please click the link below' => '', 'In order to complete your request, please click the link below' => '', 'In order to finish your registration, we need you to enter following fields' => '', + 'Inactive' => '', 'Information' => '', 'Invalid login or password' => '', 'Invalid or expired link' => '', @@ -129,6 +134,7 @@ return [ 'It will be deleted forever' => '', 'Items' => '', 'Joined on {0, date}' => '', + 'Last activity' => '', 'Last login IP' => '', 'Last login time' => '', 'Last password change' => '', @@ -187,11 +193,15 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => '', 'Select rule...' => '', 'Send password recovery email' => '', + 'Session ID' => '', + 'Session history' => '', 'Sign in' => '', 'Sign up' => '', 'Something went wrong' => '', + 'Status' => '', 'Submit' => '', 'Switch identities is disabled.' => '', + 'Terminate all sessions' => '', 'Thank you for signing up on {0}' => '', 'Thank you, registration is now complete.' => '', 'The "recaptcha" component must be configured.' => '', @@ -233,7 +243,9 @@ return [ 'Update rule' => '', 'Update user account' => '', 'Updated at' => '', + 'User ID' => '', 'User account could not be created.' => '', + 'User agent' => '', 'User block status has been updated.' => '', 'User could not be registered.' => '', 'User has been confirmed' => '', @@ -259,6 +271,7 @@ return [ 'You can connect multiple accounts to be able to log in using them' => '', 'You cannot remove your own account' => '', 'You need to confirm your email address' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your account details have been updated' => '', 'Your account has been blocked' => '', 'Your account has been blocked.' => '', @@ -279,6 +292,4 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', '{0} cannot be blank.' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/de-DU/usuario.php b/src/User/resources/i18n/de-DU/usuario.php index f3bffff..5478f88 100644 --- a/src/User/resources/i18n/de-DU/usuario.php +++ b/src/User/resources/i18n/de-DU/usuario.php @@ -275,11 +275,30 @@ return [ '{0} cannot be blank.' => '{0} darf nicht leer sein.', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', 'Data privacy' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Submit' => '', 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', 'A message has been sent to your email address. ' => '@@Eine Nachricht wurde an Deine E-Mail Adresse gesendet@@', 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', 'Now you can resume the login process' => '@@@@', + 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', + 'Current' => '', + 'Data privacy' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', + 'Submit' => '', + 'Terminate all sessions' => '', + 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', + 'Your consent is required to work with this site' => '', + 'A message has been sent to your email address. ' => '@@Eine Nachricht wurde an Deine E-Mail Adresse gesendet@@', ]; diff --git a/src/User/resources/i18n/de/usuario.php b/src/User/resources/i18n/de/usuario.php index 3344d82..139b508 100644 --- a/src/User/resources/i18n/de/usuario.php +++ b/src/User/resources/i18n/de/usuario.php @@ -277,8 +277,25 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '{0, date, dd. MMM YYYY, HH:mm}', '{0, date, MMMM dd, YYYY HH:mm}' => '{0, date, dd. MMMM YYYY, HH:mm}', '{0} cannot be blank.' => '{0} darf nicht leer sein.', + 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', + 'Current' => '', + 'Data privacy' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', + 'Submit' => '', + 'Terminate all sessions' => '', + 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', + 'Your consent is required to work with this site' => '', 'Information' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', + 'If you haven\'t received a password, you can reset it at' => '', + 'Information' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', ]; diff --git a/src/User/resources/i18n/es/usuario.php b/src/User/resources/i18n/es/usuario.php index d5cfe41..274c9ad 100644 --- a/src/User/resources/i18n/es/usuario.php +++ b/src/User/resources/i18n/es/usuario.php @@ -276,11 +276,22 @@ return [ 'privacy policy' => 'política de privacidad', '{0, date, MMMM dd, YYYY HH:mm}' => '{0, date, dd MMMM, YYYY HH:mm}', '{0} cannot be blank.' => '{0} no puede estar vacío.', + 'If you haven\'t received a password, you can reset it at' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', + 'Active' => '', + 'Current' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', + 'Terminate all sessions' => '', + 'User ID' => '', + 'User agent' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', '{0, date, MMM dd, YYYY HH:mm}' => '', 'An email has been sent with instructions for resetting your password' => '@@Se ha enviado un correo electrónico con instrucciones para restablecer su contraseña@@', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', 'Two factor authentication protects you against stolen credentials' => '@@La autenticación de dos factores le protege del robo de credenciales@@', ]; diff --git a/src/User/resources/i18n/et/usuario.php b/src/User/resources/i18n/et/usuario.php index a873ba6..c29df1a 100644 --- a/src/User/resources/i18n/et/usuario.php +++ b/src/User/resources/i18n/et/usuario.php @@ -268,17 +268,28 @@ return [ 'privacy policy' => 'privaatsuspoliitika', '{0} cannot be blank.' => '{0} ei või olla tühi.', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', 'Authentication rule class {0} can not be instantiated' => '', + 'Current' => '', 'Data privacy' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Rule class must extend "yii\\rbac\\Rule".' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', 'Submit' => '', + 'Terminate all sessions' => '', 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', 'VKontakte' => '', 'Yandex' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/fa-IR/usuario.php b/src/User/resources/i18n/fa-IR/usuario.php index c64df14..d17ea3b 100644 --- a/src/User/resources/i18n/fa-IR/usuario.php +++ b/src/User/resources/i18n/fa-IR/usuario.php @@ -151,6 +151,13 @@ return [ 'Your profile has been updated' => 'پروفایل شما بروز شد', '{0, date, MMMM dd, YYYY HH:mm}' => '{0, date, dd MMMM, YYYY HH:mm}', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Account' => '', + 'Account confirmation' => '', + 'Account details' => '', + 'Account details have been updated' => '', + 'Account settings' => '', + 'Active' => '', + 'Already registered? Sign in!' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'Are you sure you want to switch to this user for the rest of this Session?' => '', 'Are you sure you wish the user to change their password at next login?' => '', @@ -194,13 +201,23 @@ return [ 'Force password change at next login' => '', 'Here you can download your personal data in a comma separated values format.' => '', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', + 'IP' => '', + 'If you already registered, sign in and connect this account on settings page' => '', + 'If you cannot click the link, please try pasting the text into your browser' => '', + 'If you did not make this request you can ignore this email' => '', 'Impersonate this user' => '', 'In order to finish your registration, we need you to enter following fields' => '', + 'Inactive' => '', + 'Information' => '', + 'Invalid login or password' => '', + 'Invalid or expired link' => '', 'Invalid password' => '', 'Invalid two factor authentication code' => '', 'Invalid value' => '', 'It will be deleted forever' => '', 'Items' => '', + 'Joined on {0, date}' => '', + 'Last activity' => '', 'Last login IP' => '', 'Last login time' => '', 'Last password change' => '', @@ -228,6 +245,9 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => '', 'Select rule...' => '', 'Send password recovery email' => '', + 'Sign in' => '', + 'Sign up' => '', + 'Something went wrong' => '', 'Submit' => '', 'Switch identities is disabled.' => '', 'The "recaptcha" component must be configured.' => '', @@ -259,7 +279,9 @@ return [ 'Update role' => '', 'Update rule' => '', 'Updated at' => '', + 'User ID' => '', 'User account could not be created.' => '', + 'User agent' => '', 'User block status has been updated.' => '', 'User could not be registered.' => '', 'User will be required to change password at next login' => '', @@ -270,6 +292,7 @@ return [ 'We have sent confirmation links to both old and new email addresses. You must click both links to complete your request.' => '', 'You are about to delete all your personal data from this site.' => '', 'You cannot remove your own account' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your account has been completely deleted' => '', 'Your consent is required to register' => '', 'Your consent is required to work with this site' => '', @@ -279,8 +302,4 @@ return [ 'privacy policy' => '', '{0, date, MMM dd, YYYY HH:mm}' => '', '{0} cannot be blank.' => '', - 'An email has been sent with instructions for resetting your password' => '@@ایمیلی حاوی راهنمایی برای تنظیم مجدد رمز عبور به شما ارسال شد@@', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', - 'Registration ip' => '@@ای پی ثبت نام@@', ]; diff --git a/src/User/resources/i18n/fi/usuario.php b/src/User/resources/i18n/fi/usuario.php index 59af1ed..85cb688 100644 --- a/src/User/resources/i18n/fi/usuario.php +++ b/src/User/resources/i18n/fi/usuario.php @@ -28,6 +28,7 @@ return [ 'Account details' => '', 'Account details have been updated' => '', 'Account settings' => '', + 'Active' => '', 'Already registered? Sign in!' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'An error occurred processing your request' => '', @@ -81,6 +82,7 @@ return [ 'Create new rule' => '', 'Created at' => '', 'Credentials will be sent to the user by email' => '', + 'Current' => '', 'Current password' => '', 'Current password is not valid' => '', 'Data privacy' => '', @@ -113,13 +115,16 @@ return [ 'Hello' => '', 'Here you can download your personal data in a comma separated values format.' => '', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', + 'IP' => '', 'If you already registered, sign in and connect this account on settings page' => '', 'If you cannot click the link, please try pasting the text into your browser' => '', 'If you did not make this request you can ignore this email' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Impersonate this user' => '', 'In order to complete your registration, please click the link below' => '', 'In order to complete your request, please click the link below' => '', 'In order to finish your registration, we need you to enter following fields' => '', + 'Inactive' => '', 'Information' => '', 'Invalid login or password' => '', 'Invalid or expired link' => '', @@ -129,6 +134,7 @@ return [ 'It will be deleted forever' => '', 'Items' => '', 'Joined on {0, date}' => '', + 'Last activity' => '', 'Last login IP' => '', 'Last login time' => '', 'Last password change' => '', @@ -187,11 +193,15 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => '', 'Select rule...' => '', 'Send password recovery email' => '', + 'Session ID' => '', + 'Session history' => '', 'Sign in' => '', 'Sign up' => '', 'Something went wrong' => '', + 'Status' => '', 'Submit' => '', 'Switch identities is disabled.' => '', + 'Terminate all sessions' => '', 'Thank you for signing up on {0}' => '', 'Thank you, registration is now complete.' => '', 'The "recaptcha" component must be configured.' => '', @@ -233,7 +243,9 @@ return [ 'Update rule' => '', 'Update user account' => '', 'Updated at' => '', + 'User ID' => '', 'User account could not be created.' => '', + 'User agent' => '', 'User block status has been updated.' => '', 'User could not be registered.' => '', 'User has been confirmed' => '', @@ -259,6 +271,7 @@ return [ 'You can connect multiple accounts to be able to log in using them' => '', 'You cannot remove your own account' => '', 'You need to confirm your email address' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your account details have been updated' => '', 'Your account has been blocked' => '', 'Your account has been blocked.' => '', @@ -279,6 +292,4 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', '{0} cannot be blank.' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/fr/usuario.php b/src/User/resources/i18n/fr/usuario.php index 0126a73..29eaf22 100644 --- a/src/User/resources/i18n/fr/usuario.php +++ b/src/User/resources/i18n/fr/usuario.php @@ -273,12 +273,22 @@ return [ '{0, date, MMMM dd, YYYY HH:mm}' => '{0, date, dd MMMM YYYY HH:mm}', '{0} cannot be blank.' => '{0} ne peut être vide.', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', + 'Current' => '', 'Data privacy' => '', + 'If you haven\'t received a password, you can reset it at' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', 'Submit' => '', + 'Terminate all sessions' => '', 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', '{0, date, MMM dd, YYYY HH:mm}' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/hr/usuario.php b/src/User/resources/i18n/hr/usuario.php index 59af1ed..4aff8ed 100644 --- a/src/User/resources/i18n/hr/usuario.php +++ b/src/User/resources/i18n/hr/usuario.php @@ -28,6 +28,7 @@ return [ 'Account details' => '', 'Account details have been updated' => '', 'Account settings' => '', + 'Active' => '', 'Already registered? Sign in!' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'An error occurred processing your request' => '', @@ -81,6 +82,7 @@ return [ 'Create new rule' => '', 'Created at' => '', 'Credentials will be sent to the user by email' => '', + 'Current' => '', 'Current password' => '', 'Current password is not valid' => '', 'Data privacy' => '', @@ -112,14 +114,17 @@ return [ 'Gravatar email' => '', 'Hello' => '', 'Here you can download your personal data in a comma separated values format.' => '', + 'IP' => '', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', 'If you already registered, sign in and connect this account on settings page' => '', 'If you cannot click the link, please try pasting the text into your browser' => '', 'If you did not make this request you can ignore this email' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Impersonate this user' => '', 'In order to complete your registration, please click the link below' => '', 'In order to complete your request, please click the link below' => '', 'In order to finish your registration, we need you to enter following fields' => '', + 'Inactive' => '', 'Information' => '', 'Invalid login or password' => '', 'Invalid or expired link' => '', @@ -129,6 +134,7 @@ return [ 'It will be deleted forever' => '', 'Items' => '', 'Joined on {0, date}' => '', + 'Last activity' => '', 'Last login IP' => '', 'Last login time' => '', 'Last password change' => '', @@ -187,11 +193,15 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => '', 'Select rule...' => '', 'Send password recovery email' => '', + 'Session ID' => '', + 'Session history' => '', 'Sign in' => '', 'Sign up' => '', 'Something went wrong' => '', + 'Status' => '', 'Submit' => '', 'Switch identities is disabled.' => '', + 'Terminate all sessions' => '', 'Thank you for signing up on {0}' => '', 'Thank you, registration is now complete.' => '', 'The "recaptcha" component must be configured.' => '', @@ -233,7 +243,9 @@ return [ 'Update rule' => '', 'Update user account' => '', 'Updated at' => '', + 'User ID' => '', 'User account could not be created.' => '', + 'User agent' => '', 'User block status has been updated.' => '', 'User could not be registered.' => '', 'User has been confirmed' => '', @@ -259,6 +271,7 @@ return [ 'You can connect multiple accounts to be able to log in using them' => '', 'You cannot remove your own account' => '', 'You need to confirm your email address' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your account details have been updated' => '', 'Your account has been blocked' => '', 'Your account has been blocked.' => '', @@ -279,6 +292,4 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', '{0} cannot be blank.' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/hu/usuario.php b/src/User/resources/i18n/hu/usuario.php index 8c3a1f5..235a30b 100644 --- a/src/User/resources/i18n/hu/usuario.php +++ b/src/User/resources/i18n/hu/usuario.php @@ -270,35 +270,26 @@ return [ '{0, date, MMMM dd, YYYY HH:mm}' => '{0, dátum, MMMM dd, ÉÉÉÉ HH: mm}', '{0} cannot be blank.' => '{0} nem lehet üres.', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', + 'Current' => '', 'Data privacy' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Rule class name' => '', 'Select rule...' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', 'Submit' => '', + 'Terminate all sessions' => '', 'Two factor authentication protects you in case of stolen credentials' => '', 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', - 'A message has been sent to your email address. ' => '@@Üzenet érkezett az e-mail címedre.@@', - 'An email has been sent with instructions for resetting your password' => '@@E-mailt küldtek a jelszó visszaállításával kapcsolatos utasításokkal@@', - 'Awesome, almost there. ' => '@@Hurrá, majdnem kész.@@', - 'Disable Two-Factor Auth' => '@@Letiltja a kétütemű hitelesítést@@', - 'Enable Two-factor auth' => '@@Engedélyezze a kétütemű hitelesítést@@', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'I aggree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '@@Aggregálom a személyes adataim feldolgozását és a cookie-k használatát a webhely működésének megkönnyítése érdekében. További információért olvassa el a {privacyPolicy}@@', - 'Invalid two-factor code' => '@@Érvénytelen kétütemű kód@@', - 'Last login' => '@@Utolsó bejelentkezés@@', - 'Now you can resume the login process' => '@@@@', - 'This will disable two-factor auth. Are you sure?' => '@@Ez letiltja a kétütemű hitelesítést. biztos vagy ebben?@@', - 'Two Factor Authentication' => '@@Két tényező hitelesítés@@', - 'Two factor authentication protects you against stolen credentials' => '@@Két tényező-hitelesítés megvédi az ellopott hitelesítő adatokat@@', - 'Two factor successfully enabled.' => '@@Két tényező sikeresen bekapcsolt.@@', - 'Two-Factor Authentication' => '@@Két faktoros hitelesítés@@', - 'Two-factor auth protects you against stolen credentials' => '@@A kétütemű auth védelmet nyújt az ellopott hitelesítő adatok ellen@@', - 'Two-factor authentication code' => '@@Kétszeres hitelesítési kód@@', - 'Two-factor authorization has been disabled.' => '@@A kétütemű engedélyezés le van tiltva.@@', - 'Two-factor code' => '@@Kétszámjegyű kód@@', - 'Unable to disable two-factor authorization.' => '@@Nem sikerült letiltani a kétütemű engedélyezést.@@', - 'We couldn\'t re-send the mail to confirm your address. ' => '@@A cím megerősítéséhez nem tudtuk újra elküldeni az e-mailt.@@', - 'We have sent confirmation links to both old and new email addresses. ' => '@@Megerősítő linkeket küldtünk régi és új e-mail címekre.@@', ]; diff --git a/src/User/resources/i18n/it/usuario.php b/src/User/resources/i18n/it/usuario.php index ac97d23..24e5254 100644 --- a/src/User/resources/i18n/it/usuario.php +++ b/src/User/resources/i18n/it/usuario.php @@ -279,6 +279,24 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '{0, date, MMM dd, YYYY HH:mm}', '{0, date, MMMM dd, YYYY HH:mm}' => '{0, date, dd MMMM YYYY HH:mm}', '{0} cannot be blank.' => '{0} non può essere vuoto.', - 'An email has been sent with instructions for resetting your password' => '@@È stata inviata un\'email con le istruzioni per azzerare la tua password@@', - 'Now you can resume the login process' => '@@Ora puoi riprendere il processo di autenticazione@@', + 'If you haven\'t received a password, you can reset it at' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', + 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', + 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', + 'Current' => '', + 'Data privacy' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', + 'Submit' => '', + 'Terminate all sessions' => '', + 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', + 'Your consent is required to work with this site' => '', + '{0, date, MMM dd, YYYY HH:mm}' => '', ]; diff --git a/src/User/resources/i18n/kk/usuario.php b/src/User/resources/i18n/kk/usuario.php index 59af1ed..2c0b452 100644 --- a/src/User/resources/i18n/kk/usuario.php +++ b/src/User/resources/i18n/kk/usuario.php @@ -28,6 +28,7 @@ return [ 'Account details' => '', 'Account details have been updated' => '', 'Account settings' => '', + 'Active' => '', 'Already registered? Sign in!' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'An error occurred processing your request' => '', @@ -81,6 +82,7 @@ return [ 'Create new rule' => '', 'Created at' => '', 'Credentials will be sent to the user by email' => '', + 'Current' => '', 'Current password' => '', 'Current password is not valid' => '', 'Data privacy' => '', @@ -112,14 +114,18 @@ return [ 'Gravatar email' => '', 'Hello' => '', 'Here you can download your personal data in a comma separated values format.' => '', + 'IP' => '', + 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', 'If you already registered, sign in and connect this account on settings page' => '', 'If you cannot click the link, please try pasting the text into your browser' => '', 'If you did not make this request you can ignore this email' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Impersonate this user' => '', 'In order to complete your registration, please click the link below' => '', 'In order to complete your request, please click the link below' => '', 'In order to finish your registration, we need you to enter following fields' => '', + 'Inactive' => '', 'Information' => '', 'Invalid login or password' => '', 'Invalid or expired link' => '', @@ -129,6 +135,7 @@ return [ 'It will be deleted forever' => '', 'Items' => '', 'Joined on {0, date}' => '', + 'Last activity' => '', 'Last login IP' => '', 'Last login time' => '', 'Last password change' => '', @@ -187,11 +194,15 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => '', 'Select rule...' => '', 'Send password recovery email' => '', + 'Session ID' => '', + 'Session history' => '', 'Sign in' => '', 'Sign up' => '', 'Something went wrong' => '', + 'Status' => '', 'Submit' => '', 'Switch identities is disabled.' => '', + 'Terminate all sessions' => '', 'Thank you for signing up on {0}' => '', 'Thank you, registration is now complete.' => '', 'The "recaptcha" component must be configured.' => '', @@ -233,7 +244,9 @@ return [ 'Update rule' => '', 'Update user account' => '', 'Updated at' => '', + 'User ID' => '', 'User account could not be created.' => '', + 'User agent' => '', 'User block status has been updated.' => '', 'User could not be registered.' => '', 'User has been confirmed' => '', @@ -259,6 +272,7 @@ return [ 'You can connect multiple accounts to be able to log in using them' => '', 'You cannot remove your own account' => '', 'You need to confirm your email address' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your account details have been updated' => '', 'Your account has been blocked' => '', 'Your account has been blocked.' => '', @@ -279,6 +293,4 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', '{0} cannot be blank.' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/lt/usuario.php b/src/User/resources/i18n/lt/usuario.php index 59af1ed..85cb688 100644 --- a/src/User/resources/i18n/lt/usuario.php +++ b/src/User/resources/i18n/lt/usuario.php @@ -28,6 +28,7 @@ return [ 'Account details' => '', 'Account details have been updated' => '', 'Account settings' => '', + 'Active' => '', 'Already registered? Sign in!' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'An error occurred processing your request' => '', @@ -81,6 +82,7 @@ return [ 'Create new rule' => '', 'Created at' => '', 'Credentials will be sent to the user by email' => '', + 'Current' => '', 'Current password' => '', 'Current password is not valid' => '', 'Data privacy' => '', @@ -113,13 +115,16 @@ return [ 'Hello' => '', 'Here you can download your personal data in a comma separated values format.' => '', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', + 'IP' => '', 'If you already registered, sign in and connect this account on settings page' => '', 'If you cannot click the link, please try pasting the text into your browser' => '', 'If you did not make this request you can ignore this email' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Impersonate this user' => '', 'In order to complete your registration, please click the link below' => '', 'In order to complete your request, please click the link below' => '', 'In order to finish your registration, we need you to enter following fields' => '', + 'Inactive' => '', 'Information' => '', 'Invalid login or password' => '', 'Invalid or expired link' => '', @@ -129,6 +134,7 @@ return [ 'It will be deleted forever' => '', 'Items' => '', 'Joined on {0, date}' => '', + 'Last activity' => '', 'Last login IP' => '', 'Last login time' => '', 'Last password change' => '', @@ -187,11 +193,15 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => '', 'Select rule...' => '', 'Send password recovery email' => '', + 'Session ID' => '', + 'Session history' => '', 'Sign in' => '', 'Sign up' => '', 'Something went wrong' => '', + 'Status' => '', 'Submit' => '', 'Switch identities is disabled.' => '', + 'Terminate all sessions' => '', 'Thank you for signing up on {0}' => '', 'Thank you, registration is now complete.' => '', 'The "recaptcha" component must be configured.' => '', @@ -233,7 +243,9 @@ return [ 'Update rule' => '', 'Update user account' => '', 'Updated at' => '', + 'User ID' => '', 'User account could not be created.' => '', + 'User agent' => '', 'User block status has been updated.' => '', 'User could not be registered.' => '', 'User has been confirmed' => '', @@ -259,6 +271,7 @@ return [ 'You can connect multiple accounts to be able to log in using them' => '', 'You cannot remove your own account' => '', 'You need to confirm your email address' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your account details have been updated' => '', 'Your account has been blocked' => '', 'Your account has been blocked.' => '', @@ -279,6 +292,4 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', '{0} cannot be blank.' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/nl/usuario.php b/src/User/resources/i18n/nl/usuario.php index 37df1e7..394afa5 100644 --- a/src/User/resources/i18n/nl/usuario.php +++ b/src/User/resources/i18n/nl/usuario.php @@ -270,41 +270,25 @@ return [ '{0, date, MMMM dd, YYYY HH:mm}' => '{0, date, MMMM dd, YYYY HH:mm}\'', '{0} cannot be blank.' => '{0} kan niet leeg zijn.', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', + 'Current' => '', 'Data privacy' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Rule class name' => '', 'Select rule...' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', 'Submit' => '', + 'Terminate all sessions' => '', 'Two factor authentication protects you in case of stolen credentials' => '', 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', - 'A message has been sent to your email address. ' => '@@Een bericht werd naar jouw emailadres verzonden@@', - 'An email has been sent with instructions for resetting your password' => '@@Er werd een email verstuurd met instructies om jouw wachtwoord te resetten@@', - 'Awesome, almost there. ' => '@@Super, bijna klaar.@@', - 'Class "{0}" does not exist' => '@@Class "{0} bestaat niet@@', - 'Disable Two-Factor Auth' => '@@Tweetraps authenticatie uitschakelen@@', - 'Enable Two-factor auth' => '@@Tweetraps authenticatie inschakelen@@', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'I aggree processing of my personal data and the use of cookies - to facilitate the operation of this site. For more information read our {privacyPolicy}' => '@@Ik ga akkoord dat mijn persoonlijke data en cookies worden verwerkt voor het gebruik van deze website. Voor meer informatie lees onze {privacyPolicy}@@', - 'I aggree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '@@Ik ga akkoord dat mijn persoonlijke data en cookies worden verwerkt voor het gebruik van deze website. Voor meer informatie lees onze {privacyPolicy}@@', - 'Invalid two-factor code' => '@@Ongeldige tweetraps authenticatie code@@', - 'Last login' => '@@Laatste login@@', - 'Now you can resume the login process' => '@@@@', - 'Registration ip' => '@@Registratie IP@@', - 'Rule class can not be instantiated' => '@@Registratie IP@@', - 'Rule class must extend "yii\\rbac\\Rule"' => '@@Regel klasse moet worden uitgebreid met "yii\\rbac\\Rule"@@', - 'This will disable two-factor auth. Are you sure?' => '@@Dit zal de tweetraps authenticatie uitschakelen. Ben je zeker?@@', - 'Two Factor Authentication' => '@@Tweetraps authenticatie@@', - 'Two factor authentication protects you against stolen credentials' => '@@Tweetraps authenticatie beschermt je tegen gestolen inloggegevens@@', - 'Two factor successfully enabled.' => '@@Tweetraps authenticatie ingeschakeld@@', - 'Two-Factor Authentication' => '@@Tweetraps authenticatie@@', - 'Two-factor auth protects you against stolen credentials' => '@@Tweetraps authenticatie beschermt je tegen gestolen authenticatie gegevens@@', - 'Two-factor authentication code' => '@@Tweetraps authenticatie code@@', - 'Two-factor authorization has been disabled.' => '@@Tweetraps authenticatie werd uitgeschakeld.@@', - 'Two-factor code' => '@@Tweetraps authenticatie code@@', - 'Unable to disable two-factor authorization.' => '@@Tweetraps authenticatie kon niet worden uitgeschakeld@@', - 'We couldn\'t re-send the mail to confirm your address. ' => '@@Wij konden de email bevestigingsmail niet opnieuw naar jouw adres verzenden.@@', - 'We have sent confirmation links to both old and new email addresses. ' => '@@We hebben de bevestigingsmail naar zowel jouw oud als nieuw emailadres verzonden.@@', ]; diff --git a/src/User/resources/i18n/pl/usuario.php b/src/User/resources/i18n/pl/usuario.php index 82b2909..60d799e 100644 --- a/src/User/resources/i18n/pl/usuario.php +++ b/src/User/resources/i18n/pl/usuario.php @@ -270,30 +270,26 @@ return [ '{0, date, MMMM dd, YYYY HH:mm}' => '{0, date, dd MMMM YYYY, HH:mm}', '{0} cannot be blank.' => '{0} nie może pozostać bez wartości', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', + 'Current' => '', 'Data privacy' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Rule class name' => '', 'Select rule...' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', 'Submit' => '', + 'Terminate all sessions' => '', 'Two factor authentication protects you in case of stolen credentials' => '', 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', - 'An email has been sent with instructions for resetting your password' => '@@Email z instrukcją resetowania hasła został wysłany@@', - 'Disable Two-Factor Auth' => '@@Wyłącz uwierzytelnianie dwuetapowe@@', - 'Enable Two-factor auth' => '@@Włącz uwierzytelnianie dwuetapowe@@', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Invalid two-factor code' => '@@Nieprawidłowy kod uwierzytelniania dwuetapowego@@', - 'Last login' => '@@Data ostatniego logowania@@', - 'Now you can resume the login process' => '@@@@', - 'This will disable two-factor auth. Are you sure?' => '@@To wyłączy uwierzytelnianie dwuetapowe. Czy jesteś pewny?@@', - 'Two Factor Authentication' => '@@Uwierzytelnianie dwuetapowe@@', - 'Two factor authentication protects you against stolen credentials' => '@@Uwierzytelnianie dwuetapowe chroni Cię przed kradzieżą danych logowania@@', - 'Two factor successfully enabled.' => '@@Dwuetapowe uwierzytelnianie poprawnie włączone.@@', - 'Two-Factor Authentication' => '@@Uwierzytelnianie dwuetapowe@@', - 'Two-factor auth protects you against stolen credentials' => '@@Uwierzytelnianie dwuetapowe chroni Cię przed kradzieżą danych logowania@@', - 'Two-factor authentication code' => '@@Kod uwierzytelniania dwuetapowego@@', - 'Two-factor authorization has been disabled.' => '@@Dwuetapowa autoryzacja została wyłączona.@@', - 'Two-factor code' => '@@Kod dwuetapowy@@', - 'Unable to disable two-factor authorization.' => '@@Nie można wyłączyć dwuetapowej autoryzacji.@@', ]; diff --git a/src/User/resources/i18n/pt-BR/usuario.php b/src/User/resources/i18n/pt-BR/usuario.php index dd165e1..c2d8a19 100644 --- a/src/User/resources/i18n/pt-BR/usuario.php +++ b/src/User/resources/i18n/pt-BR/usuario.php @@ -270,41 +270,26 @@ return [ '{0, date, MMMM dd, YYYY HH:mm}' => '{0, date, MMMM dd, YYYY HH:mm}', '{0} cannot be blank.' => '{0} não pode estar em branco', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', + 'Current' => '', 'Data privacy' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Rule class name' => '', 'Select rule...' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', 'Submit' => '', + 'Terminate all sessions' => '', 'Two factor authentication protects you in case of stolen credentials' => '', 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', - 'A message has been sent to your email address. ' => '@@Uma mensagem foi enviada para o seu endereço de e-mail.@@', - 'An email has been sent with instructions for resetting your password' => '@@Um e-mail foi enviado com instruções para redefinir sua senha@@', - 'Awesome, almost there. ' => '@@Incrível, quase lá.@@', - 'Class "{0}" does not exist' => '@@A classe "{0}" não existe@@', - 'Disable Two-Factor Auth' => '@@Desabilitar autenticação em dois fatores@@', - 'Enable Two-factor auth' => '@@Habilitar autenticação em dois fatores@@', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'I aggree processing of my personal data and the use of cookies - to facilitate the operation of this site. For more information read our {privacyPolicy}' => '@@Concordo com o processamento de meus dados pessoais e o uso de cookies para facilitar a operação deste site. Para mais informações, leia nosso {privacyPolicy}@@', - 'I aggree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '@@Concordo com o processamento de meus dados pessoais e o uso de cookies para facilitar a operação deste site. Para mais informações, leia nosso {privacyPolicy}@@', - 'Invalid two-factor code' => '@@Código de dois fatores inválido@@', - 'Last login' => '@@Último login@@', - 'Now you can resume the login process' => '@@@@', - 'Registration ip' => '@@IP de registro@@', - 'Rule class can not be instantiated' => '@@A classe de regras não pode ser instanciada@@', - 'Rule class must extend "yii\\rbac\\Rule"' => '@@A classe de regras deve estender de "yii\\rbac\\Rule"@@', - 'This will disable two-factor auth. Are you sure?' => '@@Isso desativará a autenticação de dois fatores. Você tem certeza?@@', - 'Two Factor Authentication' => '@@Autenticação de dois fatores@@', - 'Two factor authentication protects you against stolen credentials' => '@@A autenticação de dois fatores protege você contra credenciais roubadas@@', - 'Two factor successfully enabled.' => '@@Dois fatores habilitados com sucesso.@@', - 'Two-Factor Authentication' => '@@Autenticação de dois fatores@@', - 'Two-factor auth protects you against stolen credentials' => '@@Autenticação de dois fatores protege você contra credenciais roubadas@@', - 'Two-factor authentication code' => '@@Código de autenticação de dois fatores@@', - 'Two-factor authorization has been disabled.' => '@@A autorização de dois fatores foi desabilitada.@@', - 'Two-factor code' => '@@Código de dois fatores@@', - 'Unable to disable two-factor authorization.' => '@@Não é possível desabilitar a autorização de dois fatores.@@', - 'We couldn\'t re-send the mail to confirm your address. ' => '@@Não poderíamos re-enviar o correio para confirmar o seu endereço.@@', - 'We have sent confirmation links to both old and new email addresses. ' => '@@Enviamos links de confirmação para endereços de e-mail antigo e novo.@@', ]; diff --git a/src/User/resources/i18n/pt-PT/usuario.php b/src/User/resources/i18n/pt-PT/usuario.php index 56f0388..bc33ab1 100644 --- a/src/User/resources/i18n/pt-PT/usuario.php +++ b/src/User/resources/i18n/pt-PT/usuario.php @@ -257,28 +257,39 @@ return [ 'privacy policy' => 'politica de privacidade', '{0} cannot be blank.' => '{0} não pode ficar vazio.', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'Awesome, almost there. Now you need to click the confirmation link sent to your new email address.' => '', 'Awesome, almost there. Now you need to click the confirmation link sent to your old email address.' => '', 'Children' => '', 'Class' => '', + 'Current' => '', 'Data privacy' => '', 'Email' => '', 'Gravatar email' => '', + 'If you haven\'t received a password, you can reset it at' => '', + 'IP' => '', + 'Inactive' => '', 'Items' => '', + 'Last activity' => '', 'Password' => '', 'Rule class name' => '', 'Select rule...' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', 'Submit' => '', + 'Terminate all sessions' => '', 'Two factor authentication protects you in case of stolen credentials' => '', 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', 'VKontakte' => '', 'Website' => '', 'Yandex' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/ro/usuario.php b/src/User/resources/i18n/ro/usuario.php index 2c76749..45ed666 100644 --- a/src/User/resources/i18n/ro/usuario.php +++ b/src/User/resources/i18n/ro/usuario.php @@ -270,37 +270,26 @@ return [ '{0, date, MMMM dd, YYYY HH:mm}' => '{0, data, MMMM dd, AAAA HH: mm}', '{0} cannot be blank.' => '{0} nu poate fi gol.', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', + 'Current' => '', 'Data privacy' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Rule class name' => '', 'Select rule...' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', 'Submit' => '', + 'Terminate all sessions' => '', 'Two factor authentication protects you in case of stolen credentials' => '', 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', - 'A message has been sent to your email address. ' => '@@A fost trimis un mesaj la adresa dvs. de e-mail.@@', - 'An email has been sent with instructions for resetting your password' => '@@A fost trimis un e-mail cu instrucțiuni pentru resetarea parolei@@', - 'Awesome, almost there. ' => '@@Minunat, aproape gata.@@', - 'Disable Two-Factor Auth' => '@@Dezactivați autentificarea cu două factori@@', - 'Enable Two-factor auth' => '@@Activați Auth@@', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'I aggree processing of my personal data and the use of cookies - to facilitate the operation of this site. For more information read our {privacyPolicy}' => '@@Am agregat prelucrarea datelor mele personale și utilizarea cookie-urilor pentru a facilita funcționarea acestui site. Pentru mai multe informații, citiți {privacyPolicy}@@', - 'I aggree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '@@Am agregat prelucrarea datelor mele personale și utilizarea cookie-urilor pentru a facilita funcționarea acestui site. Pentru mai multe informații, citiți {privacyPolicy}@@', - 'Invalid two-factor code' => '@@Cod de două factori nevalid@@', - 'Last login' => '@@Ultima logare@@', - 'Now you can resume the login process' => '@@@@', - 'This will disable two-factor auth. Are you sure?' => '@@Aceasta va dezactiva auth-ul cu două factori. Esti sigur?@@', - 'Two Factor Authentication' => '@@Două autentificare cu factori@@', - 'Two factor authentication protects you against stolen credentials' => '@@Autentificarea cu două factori vă protejează împotriva acreditărilor furate@@', - 'Two factor successfully enabled.' => '@@Doi factori activat cu succes.@@', - 'Two-Factor Authentication' => '@@Două factori de autentificare@@', - 'Two-factor auth protects you against stolen credentials' => '@@Autostradă cu două factori vă protejează împotriva acreditărilor furate@@', - 'Two-factor authentication code' => '@@Cod de autentificare cu două factori@@', - 'Two-factor authorization has been disabled.' => '@@A fost dezactivată autorizația cu două factori.@@', - 'Two-factor code' => '@@Cod de două factori@@', - 'Unable to disable two-factor authorization.' => '@@Imposibil de dezactivat autorizația cu două factori.@@', - 'We couldn\'t re-send the mail to confirm your address. ' => '@@Nu am putut retrimite mesajul pentru a vă confirma adresa.@@', - 'We have sent confirmation links to both old and new email addresses. ' => '@@Am trimis legături de confirmare adreselor de e-mail vechi și noi.@@', ]; diff --git a/src/User/resources/i18n/ru/usuario.php b/src/User/resources/i18n/ru/usuario.php old mode 100644 new mode 100755 index d064c1a..7b3c959 --- a/src/User/resources/i18n/ru/usuario.php +++ b/src/User/resources/i18n/ru/usuario.php @@ -27,6 +27,7 @@ return [ 'Account details' => 'Детали аккаунта', 'Account details have been updated' => 'Аккаунт был обновлен', 'Account settings' => 'Настройки аккаунта', + 'Active' => 'Активно', 'Already registered? Sign in!' => 'Уже зарегистрированы? Войдите!', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => 'Письмо с инструкциями по созданию нового пароля было выслано на {email}, в случае если данный адрес связан с {appName} аккаунтом', 'An error occurred processing your request' => 'Во время выполнения запроса произошла ошибка', @@ -80,6 +81,7 @@ return [ 'Create new rule' => 'Создать правило', 'Created at' => 'Дата создания', 'Credentials will be sent to the user by email' => 'Данные для входа будут отправлены пользователю на почту', + 'Current' => 'Текущий', 'Current password' => 'Текущий пароль', 'Current password is not valid' => 'Текущий пароль введён неправильно', 'Data processing consent' => 'Cогласие на обработку данных', @@ -111,6 +113,7 @@ return [ 'Hello' => 'Здравствуйте', 'Here you can download your personal data in a comma separated values format.' => 'Здесь вы можете загрузить свои персональные данные в формате значений, разделенных запятыми.', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => 'Я соглашаюсь на обработку моих персональных данных и использование файлов cookie для облегчения работы этого сайта. Для получения дополнительной информации ознакомьтесь с нашей {privacyPolicy}', + 'IP' => 'IP', 'If you already registered, sign in and connect this account on settings page' => 'Если вы уже зарегистрированы, войдите и подключите аккаунт в настройках', 'If you cannot click the link, please try pasting the text into your browser' => 'Если вы не можете нажать на ссылку, скопируйте её и вставьте в адресную строку вашего браузера', 'If you did not make this request you can ignore this email' => 'Если вы получили это сообщение по ошибке, просто проигнорируйте или удалите его', @@ -118,6 +121,7 @@ return [ 'In order to complete your registration, please click the link below' => 'Чтобы активировать свой аккаунт, пожалуйста, нажмите на ссылку ниже', 'In order to complete your request, please click the link below' => 'Чтобы завершить запрос, нажмите на ссылку ниже', 'In order to finish your registration, we need you to enter following fields' => 'Чтобы закончить регистрацию, заполните следующие поля', + 'Inactive' => 'Не активно', 'Information' => 'Информация', 'Invalid login or password' => 'Неправильный логин или пароль', 'Invalid or expired link' => 'Ссылка неправильна или устарела', @@ -127,6 +131,7 @@ return [ 'It will be deleted forever' => 'Он будет удалён навсегда', 'Items' => 'Элементы', 'Joined on {0, date}' => 'Зарегистрирован {0, date}', + 'Last activity' => 'Последняя активность', 'Last login IP' => 'IP последнего входа', 'Last login time' => 'Время последнего входа', 'Last password change' => 'Последняя смена пароля', @@ -185,10 +190,15 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => 'Просканируйте QR-код приложением Google Authenticator App, затем вставьте временный код в поле и отправьте.', 'Select rule...' => 'Выберите правило...', 'Send password recovery email' => 'Отправить письмо с восстановлением пароля', + 'Session ID' => 'ID сесии', + 'Session history' => 'История сессий', 'Sign in' => 'Войти', 'Sign up' => 'Зарегистрироваться', 'Something went wrong' => 'Что-то пошло не так', + 'Status' => 'Статус', + 'Submit' => 'Подтвердить', 'Switch identities is disabled.' => 'Переключение на другой аккаунт отключено.', + 'Terminate all sessions' => 'Прекратить другие сеансы', 'Thank you for signing up on {0}' => 'Спасибо за регистрацию на сайте {0}', 'Thank you, registration is now complete.' => 'Поздравляем, регистрация успешно завершена!', 'The "recaptcha" component must be configured.' => 'Необходимо настроить компонент "recaptcha"', @@ -229,7 +239,9 @@ return [ 'Update rule' => 'Изменить правило', 'Update user account' => 'Обновить аккаунт пользователя', 'Updated at' => 'Дата редактирования', + 'User ID' => 'ID пользователя', 'User account could not be created.' => 'Не удалось создать аккаунт для пользователя.', + 'User agent' => 'User agent', 'User block status has been updated.' => 'Статус блокировки пользователя обновлён.', 'User could not be registered.' => 'Не удалось зарегистрировать пользователя.', 'User has been confirmed' => 'Пользователь был активирован', @@ -265,6 +277,7 @@ return [ 'Your account on {0} has been created' => 'Ваш аккаунт на сайте "{0}" был успешно создан', 'Your confirmation token is invalid or expired' => 'Ваша ссылка устарела или является ошибочной', 'Your consent is required to register' => 'Ваше согласие требуется для регистрации', + 'Your consent is required to work with this site' => 'Ваше согласие требуется для работы с этим сайтом', 'Your email address has been changed' => 'Ваш email был успешно изменён', 'Your password has expired, you must change it now' => 'Срок действия вашего пароля истек, сейчас вы должны изменить его', 'Your personal information has been removed' => 'Ваша персональная информация удалена', @@ -275,8 +288,10 @@ return [ '{0} cannot be blank.' => '{0} не может быть пустым.', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', 'Data privacy' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Submit' => '', 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', 'A message has been sent to your email address. ' => '@@Сообщение было отправлено на вашу электронную почту@@', diff --git a/src/User/resources/i18n/th/usuario.php b/src/User/resources/i18n/th/usuario.php index 59af1ed..4aff8ed 100644 --- a/src/User/resources/i18n/th/usuario.php +++ b/src/User/resources/i18n/th/usuario.php @@ -28,6 +28,7 @@ return [ 'Account details' => '', 'Account details have been updated' => '', 'Account settings' => '', + 'Active' => '', 'Already registered? Sign in!' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'An error occurred processing your request' => '', @@ -81,6 +82,7 @@ return [ 'Create new rule' => '', 'Created at' => '', 'Credentials will be sent to the user by email' => '', + 'Current' => '', 'Current password' => '', 'Current password is not valid' => '', 'Data privacy' => '', @@ -112,14 +114,17 @@ return [ 'Gravatar email' => '', 'Hello' => '', 'Here you can download your personal data in a comma separated values format.' => '', + 'IP' => '', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', 'If you already registered, sign in and connect this account on settings page' => '', 'If you cannot click the link, please try pasting the text into your browser' => '', 'If you did not make this request you can ignore this email' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Impersonate this user' => '', 'In order to complete your registration, please click the link below' => '', 'In order to complete your request, please click the link below' => '', 'In order to finish your registration, we need you to enter following fields' => '', + 'Inactive' => '', 'Information' => '', 'Invalid login or password' => '', 'Invalid or expired link' => '', @@ -129,6 +134,7 @@ return [ 'It will be deleted forever' => '', 'Items' => '', 'Joined on {0, date}' => '', + 'Last activity' => '', 'Last login IP' => '', 'Last login time' => '', 'Last password change' => '', @@ -187,11 +193,15 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => '', 'Select rule...' => '', 'Send password recovery email' => '', + 'Session ID' => '', + 'Session history' => '', 'Sign in' => '', 'Sign up' => '', 'Something went wrong' => '', + 'Status' => '', 'Submit' => '', 'Switch identities is disabled.' => '', + 'Terminate all sessions' => '', 'Thank you for signing up on {0}' => '', 'Thank you, registration is now complete.' => '', 'The "recaptcha" component must be configured.' => '', @@ -233,7 +243,9 @@ return [ 'Update rule' => '', 'Update user account' => '', 'Updated at' => '', + 'User ID' => '', 'User account could not be created.' => '', + 'User agent' => '', 'User block status has been updated.' => '', 'User could not be registered.' => '', 'User has been confirmed' => '', @@ -259,6 +271,7 @@ return [ 'You can connect multiple accounts to be able to log in using them' => '', 'You cannot remove your own account' => '', 'You need to confirm your email address' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your account details have been updated' => '', 'Your account has been blocked' => '', 'Your account has been blocked.' => '', @@ -279,6 +292,4 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', '{0} cannot be blank.' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/tr-TR/usuario.php b/src/User/resources/i18n/tr-TR/usuario.php index 59af1ed..85cb688 100644 --- a/src/User/resources/i18n/tr-TR/usuario.php +++ b/src/User/resources/i18n/tr-TR/usuario.php @@ -28,6 +28,7 @@ return [ 'Account details' => '', 'Account details have been updated' => '', 'Account settings' => '', + 'Active' => '', 'Already registered? Sign in!' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'An error occurred processing your request' => '', @@ -81,6 +82,7 @@ return [ 'Create new rule' => '', 'Created at' => '', 'Credentials will be sent to the user by email' => '', + 'Current' => '', 'Current password' => '', 'Current password is not valid' => '', 'Data privacy' => '', @@ -113,13 +115,16 @@ return [ 'Hello' => '', 'Here you can download your personal data in a comma separated values format.' => '', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', + 'IP' => '', 'If you already registered, sign in and connect this account on settings page' => '', 'If you cannot click the link, please try pasting the text into your browser' => '', 'If you did not make this request you can ignore this email' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Impersonate this user' => '', 'In order to complete your registration, please click the link below' => '', 'In order to complete your request, please click the link below' => '', 'In order to finish your registration, we need you to enter following fields' => '', + 'Inactive' => '', 'Information' => '', 'Invalid login or password' => '', 'Invalid or expired link' => '', @@ -129,6 +134,7 @@ return [ 'It will be deleted forever' => '', 'Items' => '', 'Joined on {0, date}' => '', + 'Last activity' => '', 'Last login IP' => '', 'Last login time' => '', 'Last password change' => '', @@ -187,11 +193,15 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => '', 'Select rule...' => '', 'Send password recovery email' => '', + 'Session ID' => '', + 'Session history' => '', 'Sign in' => '', 'Sign up' => '', 'Something went wrong' => '', + 'Status' => '', 'Submit' => '', 'Switch identities is disabled.' => '', + 'Terminate all sessions' => '', 'Thank you for signing up on {0}' => '', 'Thank you, registration is now complete.' => '', 'The "recaptcha" component must be configured.' => '', @@ -233,7 +243,9 @@ return [ 'Update rule' => '', 'Update user account' => '', 'Updated at' => '', + 'User ID' => '', 'User account could not be created.' => '', + 'User agent' => '', 'User block status has been updated.' => '', 'User could not be registered.' => '', 'User has been confirmed' => '', @@ -259,6 +271,7 @@ return [ 'You can connect multiple accounts to be able to log in using them' => '', 'You cannot remove your own account' => '', 'You need to confirm your email address' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your account details have been updated' => '', 'Your account has been blocked' => '', 'Your account has been blocked.' => '', @@ -279,6 +292,4 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', '{0} cannot be blank.' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/uk/usuario.php b/src/User/resources/i18n/uk/usuario.php index 7590331..9f5017c 100644 --- a/src/User/resources/i18n/uk/usuario.php +++ b/src/User/resources/i18n/uk/usuario.php @@ -273,36 +273,21 @@ return [ '{0, date, MMMM dd, YYYY HH:mm}' => '{0, date, MMMM dd, YYYY HH:mm}', '{0} cannot be blank.' => '{0} не може бути порожнім.', 'According to the European General Data Protection Regulation (GDPR) we need your consent to work with your personal data.' => '', + 'Active' => '', + 'Current' => '', 'Data privacy' => '', + 'IP' => '', + 'Inactive' => '', + 'Last activity' => '', 'Recovery message sent' => '', + 'Session ID' => '', + 'Session history' => '', + 'Status' => '', 'Submit' => '', + 'Terminate all sessions' => '', 'Unfortunately, you can not work with this site without giving us consent to process your data.' => '', + 'User ID' => '', + 'User agent' => '', 'Your consent is required to work with this site' => '', 'Your role requires 2FA, you won\'t be able to use the application until you enable it' => '', - 'A message has been sent to your email address. ' => '@@На вашу електронну адресу надіслано повідомлення@@', - 'An email has been sent with instructions for resetting your password' => '@@Лист з інструкціями по зміні пароля надіслано на електронну адресу@@', - 'Awesome, almost there. ' => '@@Чудово, майже все.@@', - 'Class "{0}" does not exist' => '@@Клас "{0}" не існує@@', - 'Disable Two-Factor Auth' => '@@Вимкнути двофакторну аутентифікацію@@', - 'Enable Two-factor auth' => '@@Увімкнути двофакторну аутентифікацію@@', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'I aggree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '@@Я даю згоду на обробку моїх персональних даних та на використання cookie даним сайтом. Для більш детальної інформації ознайомтесь з {privacyPolicy}@@', - 'Invalid two-factor code' => '@@Невірний код двофакторної авторизації@@', - 'Last login' => '@@Останній вхід@@', - 'Now you can resume the login process' => '@@@@', - 'Registration ip' => '@@IP реєстрації@@', - 'Rule class can not be instantiated' => '@@Клас Правила не може бути ініційований@@', - 'Rule class must extend "yii\\rbac\\Rule"' => '@@Клас Правила має розширювати "yii\\rbac\\Rule"@@', - 'This will disable two-factor auth. Are you sure?' => '@@Це вимкне двофакторну аутентифікацію. Ви впевнені?@@', - 'Two Factor Authentication' => '@@Двофакторна аутентифікація@@', - 'Two factor authentication protects you against stolen credentials' => '@@Двофакторна аутентифікація дає Вам додатковий захист даних авторизації@@', - 'Two factor successfully enabled.' => '@@Двофакторна аутентифікація успішно підключена@@', - 'Two-Factor Authentication' => '@@Двофакторна аутентифікація@@', - 'Two-factor auth protects you against stolen credentials' => '@@Двофакторна аутентифікація дає Вам додатковий захист даних авторизації@@', - 'Two-factor authentication code' => '@@Код двофакторної аутентифікації@@', - 'Two-factor authorization has been disabled.' => '@@Двофакторна аутентифікація відключена@@', - 'Two-factor code' => '@@Двофакторний код@@', - 'Unable to disable two-factor authorization.' => '@@Неможливо відключити двофакторну авторизацію.@@', - 'We couldn\'t re-send the mail to confirm your address. ' => '@@Ми не змогли надіслати email для підтвердження Вашої електронної адреси.@@', - 'We have sent confirmation links to both old and new email addresses. ' => '@@Ми надіслали повідомлення з підтверджуючими посиланнями на обидві Ваші електронні адреси: стару і нову.@@', ]; diff --git a/src/User/resources/i18n/vi/usuario.php b/src/User/resources/i18n/vi/usuario.php index 59af1ed..85cb688 100644 --- a/src/User/resources/i18n/vi/usuario.php +++ b/src/User/resources/i18n/vi/usuario.php @@ -28,6 +28,7 @@ return [ 'Account details' => '', 'Account details have been updated' => '', 'Account settings' => '', + 'Active' => '', 'Already registered? Sign in!' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'An error occurred processing your request' => '', @@ -81,6 +82,7 @@ return [ 'Create new rule' => '', 'Created at' => '', 'Credentials will be sent to the user by email' => '', + 'Current' => '', 'Current password' => '', 'Current password is not valid' => '', 'Data privacy' => '', @@ -113,13 +115,16 @@ return [ 'Hello' => '', 'Here you can download your personal data in a comma separated values format.' => '', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', + 'IP' => '', 'If you already registered, sign in and connect this account on settings page' => '', 'If you cannot click the link, please try pasting the text into your browser' => '', 'If you did not make this request you can ignore this email' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Impersonate this user' => '', 'In order to complete your registration, please click the link below' => '', 'In order to complete your request, please click the link below' => '', 'In order to finish your registration, we need you to enter following fields' => '', + 'Inactive' => '', 'Information' => '', 'Invalid login or password' => '', 'Invalid or expired link' => '', @@ -129,6 +134,7 @@ return [ 'It will be deleted forever' => '', 'Items' => '', 'Joined on {0, date}' => '', + 'Last activity' => '', 'Last login IP' => '', 'Last login time' => '', 'Last password change' => '', @@ -187,11 +193,15 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => '', 'Select rule...' => '', 'Send password recovery email' => '', + 'Session ID' => '', + 'Session history' => '', 'Sign in' => '', 'Sign up' => '', 'Something went wrong' => '', + 'Status' => '', 'Submit' => '', 'Switch identities is disabled.' => '', + 'Terminate all sessions' => '', 'Thank you for signing up on {0}' => '', 'Thank you, registration is now complete.' => '', 'The "recaptcha" component must be configured.' => '', @@ -233,7 +243,9 @@ return [ 'Update rule' => '', 'Update user account' => '', 'Updated at' => '', + 'User ID' => '', 'User account could not be created.' => '', + 'User agent' => '', 'User block status has been updated.' => '', 'User could not be registered.' => '', 'User has been confirmed' => '', @@ -259,6 +271,7 @@ return [ 'You can connect multiple accounts to be able to log in using them' => '', 'You cannot remove your own account' => '', 'You need to confirm your email address' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your account details have been updated' => '', 'Your account has been blocked' => '', 'Your account has been blocked.' => '', @@ -279,6 +292,4 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', '{0} cannot be blank.' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/i18n/zh-CN/usuario.php b/src/User/resources/i18n/zh-CN/usuario.php index 59af1ed..85cb688 100644 --- a/src/User/resources/i18n/zh-CN/usuario.php +++ b/src/User/resources/i18n/zh-CN/usuario.php @@ -28,6 +28,7 @@ return [ 'Account details' => '', 'Account details have been updated' => '', 'Account settings' => '', + 'Active' => '', 'Already registered? Sign in!' => '', 'An email with instructions to create a new password has been sent to {email} if it is associated with an {appName} account. Your existing password has not been changed.' => '', 'An error occurred processing your request' => '', @@ -81,6 +82,7 @@ return [ 'Create new rule' => '', 'Created at' => '', 'Credentials will be sent to the user by email' => '', + 'Current' => '', 'Current password' => '', 'Current password is not valid' => '', 'Data privacy' => '', @@ -113,13 +115,16 @@ return [ 'Hello' => '', 'Here you can download your personal data in a comma separated values format.' => '', 'I agree processing of my personal data and the use of cookies to facilitate the operation of this site. For more information read our {privacyPolicy}' => '', + 'IP' => '', 'If you already registered, sign in and connect this account on settings page' => '', 'If you cannot click the link, please try pasting the text into your browser' => '', 'If you did not make this request you can ignore this email' => '', + 'If you haven\'t received a password, you can reset it at' => '', 'Impersonate this user' => '', 'In order to complete your registration, please click the link below' => '', 'In order to complete your request, please click the link below' => '', 'In order to finish your registration, we need you to enter following fields' => '', + 'Inactive' => '', 'Information' => '', 'Invalid login or password' => '', 'Invalid or expired link' => '', @@ -129,6 +134,7 @@ return [ 'It will be deleted forever' => '', 'Items' => '', 'Joined on {0, date}' => '', + 'Last activity' => '', 'Last login IP' => '', 'Last login time' => '', 'Last password change' => '', @@ -187,11 +193,15 @@ return [ 'Scan the QrCode with Google Authenticator App, then insert its temporary code on the box and submit.' => '', 'Select rule...' => '', 'Send password recovery email' => '', + 'Session ID' => '', + 'Session history' => '', 'Sign in' => '', 'Sign up' => '', 'Something went wrong' => '', + 'Status' => '', 'Submit' => '', 'Switch identities is disabled.' => '', + 'Terminate all sessions' => '', 'Thank you for signing up on {0}' => '', 'Thank you, registration is now complete.' => '', 'The "recaptcha" component must be configured.' => '', @@ -233,7 +243,9 @@ return [ 'Update rule' => '', 'Update user account' => '', 'Updated at' => '', + 'User ID' => '', 'User account could not be created.' => '', + 'User agent' => '', 'User block status has been updated.' => '', 'User could not be registered.' => '', 'User has been confirmed' => '', @@ -259,6 +271,7 @@ return [ 'You can connect multiple accounts to be able to log in using them' => '', 'You cannot remove your own account' => '', 'You need to confirm your email address' => '', + 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}' => '', 'Your account details have been updated' => '', 'Your account has been blocked' => '', 'Your account has been blocked.' => '', @@ -279,6 +292,4 @@ return [ '{0, date, MMM dd, YYYY HH:mm}' => '', '{0, date, MMMM dd, YYYY HH:mm}' => '', '{0} cannot be blank.' => '', - 'Every user having your role has two factor authentication mandatory, you must enable it' => '@@@@', - 'Now you can resume the login process' => '@@@@', ]; diff --git a/src/User/resources/views/admin/_session-history.php b/src/User/resources/views/admin/_session-history.php new file mode 100755 index 0000000..3e6c2cf --- /dev/null +++ b/src/User/resources/views/admin/_session-history.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +use Da\User\Widget\SessionStatusWidget; +use yii\helpers\Html; +use yii\grid\GridView; +use yii\widgets\Pjax; +use Da\User\Model\SessionHistory; +use Da\User\Search\SessionHistorySearch; +use yii\web\View; +use yii\data\ActiveDataProvider; + +/** + * @var $this View + * @var $searchModel SessionHistorySearch + * @var $dataProvider ActiveDataProvider + */ +?> + +beginContent('@Da/User/resources/views/admin/update.php', ['user' => $user]) ?> +
- = Yii::t('usuario', 'If you did not make this request you can ignore this email') ?>. + = Yii::t('usuario', 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}', ['app_name' => Yii::$app->name]) ?>.
diff --git a/src/User/resources/views/mail/text/confirmation.php b/src/User/resources/views/mail/text/confirmation.php index aedb086..20a6928 100644 --- a/src/User/resources/views/mail/text/confirmation.php +++ b/src/User/resources/views/mail/text/confirmation.php @@ -22,4 +22,4 @@ = Yii::t('usuario', 'If you cannot click the link, please try pasting the text into your browser') ?>. -= Yii::t('usuario', 'If you did not make this request you can ignore this email') ?>. += Yii::t('usuario', 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}', ['app_name' => Yii::$app->name]) ?>. diff --git a/src/User/resources/views/mail/text/welcome.php b/src/User/resources/views/mail/text/welcome.php index 0905088..484209a 100644 --- a/src/User/resources/views/mail/text/welcome.php +++ b/src/User/resources/views/mail/text/welcome.php @@ -30,4 +30,4 @@ = Yii::t('usuario', 'If you cannot click the link, please try pasting the text into your browser') ?>. -= Yii::t('usuario', 'If you did not make this request you can ignore this email') ?>. += Yii::t('usuario', 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}', ['app_name' => Yii::$app->name]) ?>. diff --git a/src/User/resources/views/mail/welcome.php b/src/User/resources/views/mail/welcome.php index 38f2dee..6a54c05 100644 --- a/src/User/resources/views/mail/welcome.php +++ b/src/User/resources/views/mail/welcome.php @@ -10,6 +10,7 @@ */ use yii\helpers\Html; +use yii\helpers\Url; /** * @var \Da\User\Module $module @@ -28,6 +29,9 @@ use yii\helpers\Html; generatePasswords): ?> = Yii::t('usuario', 'We have generated a password for you') ?>: = $user->password ?> + allowPasswordRecovery): ?> + = Yii::t('usuario', 'If you haven\'t received a password, you can reset it at') ?>: = Html::a(Html::encode(Url::to(['/user/forgot'], true)), Url::to(['/user/forgot'], true)) ?> + @@ -44,5 +48,5 @@ use yii\helpers\Html;- = Yii::t('usuario', 'If you did not make this request you can ignore this email') ?>. + = Yii::t('usuario', 'You received this email because someone, possibly you or someone on your behalf, have created an account at {app_name}', ['app_name' => Yii::$app->name]) ?>.
diff --git a/src/User/resources/views/settings/_menu.php b/src/User/resources/views/settings/_menu.php old mode 100644 new mode 100755 index 9c58638..bd3c2af --- a/src/User/resources/views/settings/_menu.php +++ b/src/User/resources/views/settings/_menu.php @@ -11,9 +11,12 @@ use yii\helpers\Html; use yii\widgets\Menu; +use Da\User\Module as UserModule; +use Da\User\Model\User; -/** @var \Da\User\Model\User $user */ +/** @var User $user */ $user = Yii::$app->user->identity; +/** @var UserModule $module */ $module = Yii::$app->getModule('user'); $networksVisible = count(Yii::$app->authClientCollection->clients) > 0; @@ -41,6 +44,11 @@ $networksVisible = count(Yii::$app->authClientCollection->clients) > 0; 'items' => [ ['label' => Yii::t('usuario', 'Profile'), 'url' => ['/user/settings/profile']], ['label' => Yii::t('usuario', 'Account'), 'url' => ['/user/settings/account']], + [ + 'label' => Yii::t('usuario', 'Session history'), + 'url' => ['/user/settings/session-history'], + 'visible' => $module->enableSessionHistory, + ], ['label' => Yii::t('usuario', 'Privacy'), 'url' => ['/user/settings/privacy'], 'visible' => $module->enableGdprCompliance diff --git a/src/User/resources/views/settings/session-history.php b/src/User/resources/views/settings/session-history.php new file mode 100755 index 0000000..467ea93 --- /dev/null +++ b/src/User/resources/views/settings/session-history.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +use yii\helpers\Html; +use yii\grid\GridView; +use yii\widgets\Pjax; +use Da\User\Model\SessionHistory; +use Da\User\Search\SessionHistorySearch; +use yii\web\View; +use yii\data\ActiveDataProvider; +use Da\User\Widget\SessionStatusWidget; + +/** + * @var $this View + * @var $searchModel SessionHistorySearch + * @var $dataProvider ActiveDataProvider + */ + +$this->title = Yii::t('usuario', 'Session history'); +$this->params['breadcrumbs'][] = $this->title; +?> + += $this->render('/shared/_alert', ['module' => Yii::$app->getModule('user')]) ?> + +