From 9d391d1158e17c42e3fc78a36b81d281ec19757c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 25 Nov 2024 18:10:59 +0000 Subject: [PATCH] fix conflicts --- .semver | 4 +- CHANGELOG.md | 15 + Docs/Documentation/Authentication.md | 1 + Docs/Documentation/Configuration.md | 20 + Docs/Documentation/Translations.md | 2 +- README.md | 30 +- config/bootstrap.php | 2 +- config/users.php | 20 + resources/locales/cake_d_c_users.pot | 909 +++++++++--------- .../Traits/PasswordManagementTrait.php | 10 +- src/Controller/Traits/RegisterTrait.php | 4 +- src/Controller/Traits/UserValidationTrait.php | 5 +- .../PasswordLockout/LockoutHandler.php | 38 +- src/Identifier/PasswordLockoutIdentifier.php | 7 +- src/Model/Behavior/SocialAccountBehavior.php | 6 +- src/Model/Behavior/SocialBehavior.php | 14 +- src/Model/Table/UsersTable.php | 4 +- src/Plugin.php | 3 +- src/View/Helper/UserHelper.php | 112 ++- src/Webauthn/AuthenticateAdapter.php | 7 +- src/Webauthn/BaseAdapter.php | 5 +- src/Webauthn/PublicKeyCredentialLoader.php | 6 +- src/Webauthn/RegisterAdapter.php | 2 +- templates/Users/change_password.php | 8 +- templates/Users/login.php | 2 +- templates/Users/profile.php | 2 +- templates/Users/register.php | 7 +- ...PasswordManagementTraitIntegrationTest.php | 2 +- .../RegisterTraitIntegrationTest.php | 8 +- .../SimpleCrudTraitIntegrationTest.php | 2 +- .../Traits/Webauthn2FaTraitTest.php | 18 +- tests/TestCase/View/Helper/UserHelperTest.php | 54 ++ webroot/js/pswmeter.js | 151 +++ webroot/js/reCaptchaV3.js | 3 + 34 files changed, 957 insertions(+), 526 deletions(-) create mode 100644 webroot/js/pswmeter.js create mode 100644 webroot/js/reCaptchaV3.js diff --git a/.semver b/.semver index bd7c75ac5..683f3209a 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 14 -:minor: 1 -:patch: 0 +:minor: 3 +:patch: 1 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index 418a49658..9d32cbe57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ Changelog ========= Releases for CakePHP 5 ------------- +* 14.3.1 + * Fix duplicated rule name in rules checker +* 14.3.0 + * Update Translations.md by @MarwanSalim in #1089 + * Fix named parameter issue in _createSocialUser method for findExistingForSocialLogin #1091 by @robitmoh in #1092 + * Bug #1084 Fix issue with avatar images long URL by @flohdez in #1094 + * #1096: fixed findExistingForSocialLogin finder by @arusinowski in #1097 +* 14.2.1 + * Improve documentation about password meter. + * Fix minor bugs +* 14.2.0 + * Add password meter to display password quality + * Add integration with google reCaptcha v3, keep default using v2 +* 14.1.1 + * Add config option to customize the user foreign key field in LockoutHandler * 14.1 * New feature "Account lockout policy" * 14.0 diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 641de4289..2aa415834 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -141,6 +141,7 @@ Additionally, you can set number of attempts until lock, lockout time, time wind 'failedPasswordAttemptsModel' => 'CakeDC/Users.FailedPasswordAttempts', 'userLockoutField' => 'lockout_time',//Field in user entity used to lock the user. 'usersModel' => 'Users', + 'userForeignKeyField' => 'user_id', //Field defined in the 'failed_password_attempts' table as foreignKey of the model Users. ], ``` diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 01b960aa4..ecb3e38e5 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -54,6 +54,7 @@ and add this to your config/users.php file: ```php 'Users.reCaptcha.key' => 'YOUR RECAPTCHA KEY', 'Users.reCaptcha.secret' => 'YOUR RECAPTCHA SECRET', +'Users.reCaptcha.version' => '2', //defaults to version 2 (backward compatibility) but you can use version 3 which is recommended 'Users.reCaptcha.registration' => true, //enable on registration 'Users.reCaptcha.login' => true, //enable on login ``` @@ -64,6 +65,25 @@ Note you'll need to add google/recaptcha to your composer.json file. $ composer require google/recaptcha:@stable ``` +Configuration for Password Meter +--------------------- +Password meter is enabled by default but you can disable it or change config options adding this to your config/users.php file: + +```php +'Users.passwordMeter.enabled' => true, //enable or disable password meter. Defaults to true +'Users.passwordMeter.requiredScore' => 1, //int value from 1 to 4 (25%,50%,75%,100%). Defaults to 1 +'Users.passwordMeter.messagesList' => ['Empty password', 'Too simple', 'Simple', 'That\'s OK', 'Great password!'], //Messages for each password level (0%,25%,50%,75%,100%) +'Users.passwordMeter.pswMinLength' => 8, //Password min length, defaults to 8. It won't affect users validation in backend +'Users.passwordMeter.showMessage' => true, //shows password message +``` + +Note the score is calculated based on the following rules: + +* If you include a lower single character and an upper one ([a-zA-Z]) it increases the score by 1 +* If you include an special single character it increases the score by 1 +* If you include a digit it increases the score by 1 +* If you reaches the `pswMinLength` it increases the score by 1 + Configuration options --------------------- diff --git a/Docs/Documentation/Translations.md b/Docs/Documentation/Translations.md index 566911ea7..38e4d9f52 100644 --- a/Docs/Documentation/Translations.md +++ b/Docs/Documentation/Translations.md @@ -16,6 +16,6 @@ The Plugin is translated into several languages: * Czech (cs_CZ) by @Mapiiik * Dutch (nl_NL) by @StefanvanR -**Note:** To overwrite the plugin translations, create a file inside your project 'resources/locales//{$lang}/' folder, with the name 'Users.po' and add the strings with the new translations. +**Note:** To overwrite the plugin translations, create a file inside your project 'resources/locales//{$lang}/' folder, with the name 'cake_d_c_users.po' and add the strings with the new translations. Remember to clean the translations cache! diff --git a/README.md b/README.md index 8850fa393..58980549e 100644 --- a/README.md +++ b/README.md @@ -10,20 +10,20 @@ CakeDC Users Plugin Versions and branches --------------------- -| CakePHP | CakeDC Users Plugin | Tag | Notes | -|:--------------:|:----------------------------------------------------------:|:-----------------:| :---- | -| ^5.0 | [14.1](https://github.com/cakedc/users/tree/14.next-cake5) | 14.next-cake5-dev | beta | -| ^4.5 | [13.0](https://github.com/cakedc/users/tree/13.next-cake4) | 13.0.1 | stable | -| ^5.0 | [12.0](https://github.com/cakedc/users/tree/12.next-cake5) | 12.0 | beta | -| ^4.3 | [11.0](https://github.com/cakedc/users/tree/11.next-cake4) | 11.1.0 | stable | -| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.5 | stable | -| ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | -| ^3.7 <4.0 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | -| 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | -| 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | -| 3.4 | [5.x](https://github.com/cakedc/users/tree/5.x) | 5.2.0 | stable | -| >=3.2.9 <3.4.0 | [4.x](https://github.com/cakedc/users/tree/4.x) | 4.2.1 | stable | -| ^2.10 | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.2.0 |stable | +| CakePHP | CakeDC Users Plugin | Tag | Notes | +|:--------------:|:----------------------------------------------------------:|:------:|:---------| +| ^5.0 | [14.2](https://github.com/cakedc/users/tree/14.next-cake5) | 14.3.1 | stable | +| ^4.5 | [13.0](https://github.com/cakedc/users/tree/13.next-cake4) | 13.0.1 | stable | +| ^5.0 | [12.0](https://github.com/cakedc/users/tree/12.next-cake5) | 12.0 | beta | +| ^4.3 | [11.0](https://github.com/cakedc/users/tree/11.next-cake4) | 11.1.0 | stable | +| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.5 | stable | +| ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | +| ^3.7 <4.0 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | +| 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | +| 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | +| 3.4 | [5.x](https://github.com/cakedc/users/tree/5.x) | 5.2.0 | stable | +| >=3.2.9 <3.4.0 | [4.x](https://github.com/cakedc/users/tree/4.x) | 4.2.1 | stable | +| ^2.10 | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.2.0 | stable | The **Users** plugin covers the following features: @@ -36,6 +36,8 @@ The **Users** plugin covers the following features: * Admin management * One-Time Password for Two-Factor Authentication * Webauthn for Two-Factor Authentication (Yubico Key compatible) +* reCaptcha v3 (14.2 only) and v2 supported in all versions +* Password Meter The plugin is here to provide users related features following 2 approaches: diff --git a/config/bootstrap.php b/config/bootstrap.php index d78acc8b7..ea91386c7 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -36,6 +36,6 @@ ]; foreach ($oldConfigs as $configKey) { if (Configure::check($configKey)) { - trigger_error(__("Users plugin configuration key \"{0}\" was removed, please check migration guide https://github.com/CakeDC/users/blob/master/Docs/Documentation/Migration/8.x-9.0.md", $configKey)); + trigger_error(__d('cake_d_c/users', "Users plugin configuration key \"{0}\" was removed, please check migration guide https://github.com/CakeDC/users/blob/master/Docs/Documentation/Migration/8.x-9.0.md", $configKey)); } } diff --git a/config/users.php b/config/users.php index 3f347e18e..46c07db42 100644 --- a/config/users.php +++ b/config/users.php @@ -71,11 +71,31 @@ 'key' => null, // reCaptcha secret 'secret' => null, + // reCaptcha version. keep 2 for backward compatibility + 'version' => 2, // use reCaptcha in registration 'registration' => false, // use reCaptcha in login, valid values are false, true 'login' => false, ], + 'passwordMeter' => [ + //enable or disable password meter + 'enabled' => true, + //int value from 1 to 4 (25%,50%,75%,100%). Defaults to 3 + 'requiredScore' => 1, + //Messages for each password level (0%,25%,50%,75%,100%) + 'messagesList' => [ + __d('cake_d_c/users', 'Empty password'), + __d('cake_d_c/users', 'Too simple'), + __d('cake_d_c/users','Simple'), + __d('cake_d_c/users', 'That\'s OK'), + __d('cake_d_c/users', 'Great password!') + ], + //Password min length + 'pswMinLength' => 8, + //shows message for password score + 'showMessage' => true, + ], 'Tos' => [ // determines if the user should include tos accepted 'required' => true, diff --git a/resources/locales/cake_d_c_users.pot b/resources/locales/cake_d_c_users.pot index c2992ab07..267142b12 100644 --- a/resources/locales/cake_d_c_users.pot +++ b/resources/locales/cake_d_c_users.pot @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2022-03-11 13:46+0100\n" +"POT-Creation-Date: 2024-05-10 08:44+0000\n" "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" "Last-Translator: NAME \n" "Language-Team: LANGUAGE \n" @@ -14,907 +14,934 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: src/Controller/SocialAccountsController.php:50 -msgid "Account validated successfully" +#: ./vendor/cakedc/users/src/Command/Logic/ChangeUserActiveTrait.php:25 +#: ./vendor/cakedc/users/src/Command/UsersChangeApiTokenCommand.php:46 +#: ./vendor/cakedc/users/src/Command/UsersChangeRoleCommand.php:46 +#: ./vendor/cakedc/users/src/Command/UsersDeleteUserCommand.php:42 +#: ./vendor/cakedc/users/src/Command/UsersResetPasswordCommand.php:46 +msgid "Please enter a username." msgstr "" -#: src/Controller/SocialAccountsController.php:52 -msgid "Account could not be validated" +#: ./vendor/cakedc/users/src/Command/Logic/CreateUserTrait.php:89 +msgid "Superuser added:" msgstr "" -#: src/Controller/SocialAccountsController.php:55 -msgid "Invalid token and/or social account" +#: ./vendor/cakedc/users/src/Command/Logic/CreateUserTrait.php:91 +msgid "User added:" msgstr "" -#: src/Controller/SocialAccountsController.php:57 -#: src/Controller/SocialAccountsController.php:85 -msgid "Social Account already active" +#: ./vendor/cakedc/users/src/Command/Logic/CreateUserTrait.php:93 +msgid "Id: {0}" msgstr "" -#: src/Controller/SocialAccountsController.php:59 -msgid "Social Account could not be validated" +#: ./vendor/cakedc/users/src/Command/Logic/CreateUserTrait.php:94 +msgid "Username: {0}" msgstr "" -#: src/Controller/SocialAccountsController.php:78 -msgid "Email sent successfully" +#: ./vendor/cakedc/users/src/Command/Logic/CreateUserTrait.php:95 +msgid "Email: {0}" msgstr "" -#: src/Controller/SocialAccountsController.php:80 -msgid "Email could not be sent" +#: ./vendor/cakedc/users/src/Command/Logic/CreateUserTrait.php:96 +msgid "Role: {0}" msgstr "" -#: src/Controller/SocialAccountsController.php:83 -msgid "Invalid account" +#: ./vendor/cakedc/users/src/Command/Logic/CreateUserTrait.php:97 +msgid "Password: {0}" msgstr "" -#: src/Controller/SocialAccountsController.php:87 -msgid "Email could not be resent" +#: ./vendor/cakedc/users/src/Command/Logic/CreateUserTrait.php:99 +msgid "User could not be added:" msgstr "" -#: src/Controller/Traits/LinkSocialTrait.php:56 -msgid "Could not associate account, please try again." +#: ./vendor/cakedc/users/src/Command/Logic/CreateUserTrait.php:102 +msgid "Field: {0} Error: {1}" msgstr "" -#: src/Controller/Traits/LinkSocialTrait.php:80 -msgid "Social account was associated." +#: ./vendor/cakedc/users/src/Command/Logic/UpdateUserTrait.php:29 +msgid "The user was not found." msgstr "" -#: src/Controller/Traits/LoginTrait.php:73 -msgid "You've successfully logged out" +#: ./vendor/cakedc/users/src/Command/UsersActivateUserCommand.php:31 +msgid "Activate a specific user" msgstr "" -#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:75 -msgid "Please enable Google Authenticator first." +#: ./vendor/cakedc/users/src/Command/UsersActivateUserCommand.php:44 +msgid "User was activated: {0}" msgstr "" -#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:90 -msgid "Could not find user data" +#: ./vendor/cakedc/users/src/Command/UsersChangeApiTokenCommand.php:31 +msgid "Change the api token for a specific user" msgstr "" -#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:129 -msgid "Could not verify, please try again" +#: ./vendor/cakedc/users/src/Command/UsersChangeApiTokenCommand.php:49 +msgid "Please enter a token." msgstr "" -#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:161 -msgid "Verification code is invalid. Try again" +#: ./vendor/cakedc/users/src/Command/UsersChangeApiTokenCommand.php:58 +msgid "Api token changed for user: {0}" msgstr "" -#: src/Controller/Traits/PasswordManagementTrait.php:63 -msgid "Changing another user's password is not allowed" +#: ./vendor/cakedc/users/src/Command/UsersChangeApiTokenCommand.php:59 +msgid "New token: {0}" msgstr "" -#: src/Controller/Traits/PasswordManagementTrait.php:77 -#: src/Controller/Traits/PasswordManagementTrait.php:121 -#: src/Controller/Traits/ProfileTrait.php:54 -msgid "User was not found" +#: ./vendor/cakedc/users/src/Command/UsersChangeRoleCommand.php:31 +msgid "Change the role for a specific user" msgstr "" -#: src/Controller/Traits/PasswordManagementTrait.php:105 -#: src/Controller/Traits/PasswordManagementTrait.php:117 -#: src/Controller/Traits/PasswordManagementTrait.php:125 -msgid "Password could not be changed" +#: ./vendor/cakedc/users/src/Command/UsersChangeRoleCommand.php:49 +msgid "Please enter a role." msgstr "" -#: src/Controller/Traits/PasswordManagementTrait.php:113 -msgid "Password has been changed successfully" +#: ./vendor/cakedc/users/src/Command/UsersChangeRoleCommand.php:55 +msgid "Role changed for user: {0}" msgstr "" -#: src/Controller/Traits/PasswordManagementTrait.php:167 -msgid "Please check your email to continue with password reset process" +#: ./vendor/cakedc/users/src/Command/UsersChangeRoleCommand.php:56 +msgid "New role: {0}" msgstr "" -#: src/Controller/Traits/PasswordManagementTrait.php:170 -#: src/Shell/UsersShell.php:286 -msgid "The password token could not be generated. Please try again" +#: ./vendor/cakedc/users/src/Command/UsersDeactivateUserCommand.php:31 +msgid "Deactivate a specific user" msgstr "" -#: src/Controller/Traits/PasswordManagementTrait.php:176 -#: src/Controller/Traits/UserValidationTrait.php:124 -msgid "User {0} was not found" +#: ./vendor/cakedc/users/src/Command/UsersDeactivateUserCommand.php:44 +msgid "User was de-activated: {0}" msgstr "" -#: src/Controller/Traits/PasswordManagementTrait.php:178 -msgid "The user is not active" +#: ./vendor/cakedc/users/src/Command/UsersDeleteUserCommand.php:28 +msgid "Delete a specific user" msgstr "" -#: src/Controller/Traits/PasswordManagementTrait.php:180 -#: src/Controller/Traits/UserValidationTrait.php:119 -#: src/Controller/Traits/UserValidationTrait.php:128 -msgid "Token could not be reset" +#: ./vendor/cakedc/users/src/Command/UsersDeleteUserCommand.php:57 +msgid "The user {0} was not deleted. Please try again" msgstr "" -#: src/Controller/Traits/PasswordManagementTrait.php:204 -msgid "Google Authenticator token was successfully reset" +#: ./vendor/cakedc/users/src/Command/UsersDeleteUserCommand.php:59 +msgid "The user {0} was deleted successfully" msgstr "" -#: src/Controller/Traits/PasswordManagementTrait.php:207 -msgid "Could not reset Google Authenticator" +#: ./vendor/cakedc/users/src/Command/UsersPasswordEmailCommand.php:29 +msgid "Reset the password via email" msgstr "" -#: src/Controller/Traits/ProfileTrait.php:58 -msgid "Not authorized, please login first" +#: ./vendor/cakedc/users/src/Command/UsersPasswordEmailCommand.php:43 +msgid "Please enter a username or email." msgstr "" -#: src/Controller/Traits/RegisterTrait.php:47 -msgid "You must log out to register a new user account" +#: ./vendor/cakedc/users/src/Command/UsersPasswordEmailCommand.php:55 +msgid "Please ask the user to check the email to continue with password reset process" msgstr "" -#: src/Controller/Traits/RegisterTrait.php:86 -#: src/Controller/Traits/RegisterTrait.php:117 -msgid "The user could not be saved" +#: ./vendor/cakedc/users/src/Command/UsersPasswordEmailCommand.php:61 +msgid "The password token could not be generated. Please try again" msgstr "" -#: src/Controller/Traits/RegisterTrait.php:103 -#: src/Loader/LoginComponentLoader.php:33 -msgid "Invalid reCaptcha" +#: ./vendor/cakedc/users/src/Command/UsersResetAllPasswordsCommand.php:29 +msgid "Reset the password for all users" msgstr "" -#: src/Controller/Traits/RegisterTrait.php:151 -msgid "You have registered successfully, please log in" +#: ./vendor/cakedc/users/src/Command/UsersResetAllPasswordsCommand.php:44 +#: ./vendor/cakedc/users/src/Command/UsersResetPasswordCommand.php:49 +msgid "Please enter a password." msgstr "" -#: src/Controller/Traits/RegisterTrait.php:153 -msgid "Please validate your account before log in" +#: ./vendor/cakedc/users/src/Command/UsersResetAllPasswordsCommand.php:48 +msgid "Password changed for all users" msgstr "" -#: src/Controller/Traits/SimpleCrudTrait.php:77 -#: src/Controller/Traits/SimpleCrudTrait.php:107 -msgid "The {0} has been saved" +#: ./vendor/cakedc/users/src/Command/UsersResetAllPasswordsCommand.php:49 +#: ./vendor/cakedc/users/src/Command/UsersResetPasswordCommand.php:56 +msgid "New password: {0}" msgstr "" -#: src/Controller/Traits/SimpleCrudTrait.php:81 -#: src/Controller/Traits/SimpleCrudTrait.php:111 -msgid "The {0} could not be saved" +#: ./vendor/cakedc/users/src/Command/UsersResetPasswordCommand.php:31 +msgid "Reset the password for a specific user" msgstr "" -#: src/Controller/Traits/SimpleCrudTrait.php:131 -msgid "The {0} has been deleted" +#: ./vendor/cakedc/users/src/Command/UsersResetPasswordCommand.php:55 +msgid "Password changed for user: {0}" msgstr "" -#: src/Controller/Traits/SimpleCrudTrait.php:133 -msgid "The {0} could not be deleted" +#: ./vendor/cakedc/users/src/Controller/Component/LoginComponent.php:262 +#: ./vendor/cakedc/users/src/View/Helper/UserHelper.php:133 +msgid "Welcome, {0}" msgstr "" -#: src/Controller/Traits/U2fTrait.php:216 -msgid "U2F requires SSL." +#: ./vendor/cakedc/users/src/Controller/SocialAccountsController.php:50 +msgid "Account validated successfully" msgstr "" -#: src/Controller/Traits/UserValidationTrait.php:49 -msgid "User account validated successfully" +#: ./vendor/cakedc/users/src/Controller/SocialAccountsController.php:52 +msgid "Account could not be validated" msgstr "" -#: src/Controller/Traits/UserValidationTrait.php:51 -msgid "User account could not be validated" +#: ./vendor/cakedc/users/src/Controller/SocialAccountsController.php:55 +msgid "Invalid token and/or social account" msgstr "" -#: src/Controller/Traits/UserValidationTrait.php:54 -msgid "User already active" +#: ./vendor/cakedc/users/src/Controller/SocialAccountsController.php:57 +#: ./vendor/cakedc/users/src/Controller/SocialAccountsController.php:85 +msgid "Social Account already active" msgstr "" -#: src/Controller/Traits/UserValidationTrait.php:60 -msgid "Reset password token was validated successfully" +#: ./vendor/cakedc/users/src/Controller/SocialAccountsController.php:59 +msgid "Social Account could not be validated" msgstr "" -#: src/Controller/Traits/UserValidationTrait.php:68 -msgid "Reset password token could not be validated" +#: ./vendor/cakedc/users/src/Controller/SocialAccountsController.php:78 +msgid "Email sent successfully" msgstr "" -#: src/Controller/Traits/UserValidationTrait.php:72 -msgid "Invalid validation type" +#: ./vendor/cakedc/users/src/Controller/SocialAccountsController.php:80 +msgid "Email could not be sent" msgstr "" -#: src/Controller/Traits/UserValidationTrait.php:75 -msgid "Invalid token or user account already validated" +#: ./vendor/cakedc/users/src/Controller/SocialAccountsController.php:83 +msgid "Invalid account" msgstr "" -#: src/Controller/Traits/UserValidationTrait.php:81 -msgid "Token already expired" +#: ./vendor/cakedc/users/src/Controller/SocialAccountsController.php:87 +msgid "Email could not be resent" msgstr "" -#: src/Controller/Traits/UserValidationTrait.php:114 -msgid "Token has been reset successfully. Please check your email." +#: ./vendor/cakedc/users/src/Controller/Traits/LinkSocialTrait.php:56 +msgid "Could not associate account, please try again." msgstr "" -#: src/Controller/Traits/UserValidationTrait.php:126 -msgid "User {0} is already active" +#: ./vendor/cakedc/users/src/Controller/Traits/LinkSocialTrait.php:80 +msgid "Social account was associated." msgstr "" -#: src/Controller/Traits/Webauthn2faTrait.php:53 -#: src/Controller/Traits/Webauthn2faTrait.php:73 -msgid "User already has configured webauthn2fa" +#: ./vendor/cakedc/users/src/Controller/Traits/LoginTrait.php:73 +msgid "You've successfully logged out" msgstr "" -#: src/Controller/Traits/Webauthn2faTrait.php:77 -#: src/Controller/Traits/Webauthn2faTrait.php:122 -msgid "Register error with webauthn for user id: {0}" +#: ./vendor/cakedc/users/src/Controller/Traits/OneTimePasswordVerifyTrait.php:75 +msgid "Please enable Google Authenticator first." msgstr "" -#: src/Loader/AuthenticationServiceLoader.php:109 -msgid "Property {0}.className should be defined" +#: ./vendor/cakedc/users/src/Controller/Traits/OneTimePasswordVerifyTrait.php:90 +msgid "Could not find user data" msgstr "" -#: src/Loader/LoginComponentLoader.php:31 -msgid "Username or password is incorrect" +#: ./vendor/cakedc/users/src/Controller/Traits/OneTimePasswordVerifyTrait.php:129 +msgid "Could not verify, please try again" msgstr "" -#: src/Loader/LoginComponentLoader.php:52 -msgid "Could not proceed with social account. Please try again" +#: ./vendor/cakedc/users/src/Controller/Traits/OneTimePasswordVerifyTrait.php:161 +msgid "Verification code is invalid. Try again" msgstr "" -#: src/Loader/LoginComponentLoader.php:54 -msgid "Your user has not been validated yet. Please check your inbox for instructions" +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:64 +msgid "Changing another user's password is not allowed" msgstr "" -#: src/Loader/LoginComponentLoader.php:58 -msgid "Your social account has not been validated yet. Please check your inbox for instructions" +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:78 +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:123 +#: ./vendor/cakedc/users/src/Controller/Traits/ProfileTrait.php:51 +msgid "User was not found" msgstr "" -#: src/Mailer/UsersMailer.php:36 -msgid "Your account validation link" +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:106 +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:119 +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:127 +msgid "Password could not be changed" msgstr "" -#: src/Mailer/UsersMailer.php:63 -msgid "{0}Your reset password link" +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:115 +msgid "Password has been changed successfully" msgstr "" -#: src/Mailer/UsersMailer.php:95 -msgid "{0}Your social account validation link" +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:169 +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:178 +msgid "If the account is valid, the system will send an instructional email to the address on record." msgstr "" -#: src/Middleware/SocialAuthMiddleware.php:47 -#: templates/Users/social_email.php:16 -msgid "Please enter your email" +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:172 +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:181 +msgid "There was an error please contact Administrator" msgstr "" -#: src/Middleware/SocialAuthMiddleware.php:57 -msgid "Could not identify your account, please try again" +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:206 +msgid "Google Authenticator token was successfully reset" msgstr "" -#: src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php:112 -msgid "You are not authorized to access that location." +#: ./vendor/cakedc/users/src/Controller/Traits/PasswordManagementTrait.php:209 +msgid "Could not reset Google Authenticator" msgstr "" -#: src/Model/Behavior/AuthFinderBehavior.php:49 -msgid "Missing 'username' in options data" +#: ./vendor/cakedc/users/src/Controller/Traits/ProfileTrait.php:55 +msgid "Not authorized, please login first" msgstr "" -#: src/Model/Behavior/LinkSocialBehavior.php:52 -msgid "Social account already associated to another user" +#: ./vendor/cakedc/users/src/Controller/Traits/RegisterTrait.php:47 +msgid "You must log out to register a new user account" msgstr "" -#: src/Model/Behavior/PasswordBehavior.php:45 -msgid "Reference cannot be null" +#: ./vendor/cakedc/users/src/Controller/Traits/RegisterTrait.php:86 +#: ./vendor/cakedc/users/src/Controller/Traits/RegisterTrait.php:117 +msgid "The user could not be saved" msgstr "" -#: src/Model/Behavior/PasswordBehavior.php:50 -msgid "Token expiration cannot be empty" +#: ./vendor/cakedc/users/src/Controller/Traits/RegisterTrait.php:103 +#: ./vendor/cakedc/users/src/Loader/LoginComponentLoader.php:33 +msgid "Invalid reCaptcha" msgstr "" -#: src/Model/Behavior/PasswordBehavior.php:56 -#: src/Model/Behavior/PasswordBehavior.php:136 -msgid "User not found" +#: ./vendor/cakedc/users/src/Controller/Traits/RegisterTrait.php:151 +msgid "You have registered successfully, please log in" msgstr "" -#: src/Model/Behavior/PasswordBehavior.php:60 -#: src/Model/Behavior/RegisterBehavior.php:129 -msgid "User account already validated" +#: ./vendor/cakedc/users/src/Controller/Traits/RegisterTrait.php:153 +msgid "Please validate your account before log in" msgstr "" -#: src/Model/Behavior/PasswordBehavior.php:66 -msgid "User not active" +#: ./vendor/cakedc/users/src/Controller/Traits/SimpleCrudTrait.php:75 +#: ./vendor/cakedc/users/src/Controller/Traits/SimpleCrudTrait.php:105 +msgid "The {0} has been saved" msgstr "" -#: src/Model/Behavior/PasswordBehavior.php:141 -msgid "The current password does not match" +#: ./vendor/cakedc/users/src/Controller/Traits/SimpleCrudTrait.php:79 +#: ./vendor/cakedc/users/src/Controller/Traits/SimpleCrudTrait.php:109 +msgid "The {0} could not be saved" msgstr "" -#: src/Model/Behavior/PasswordBehavior.php:144 -msgid "You cannot use the current password as the new one" +#: ./vendor/cakedc/users/src/Controller/Traits/SimpleCrudTrait.php:129 +msgid "The {0} has been deleted" msgstr "" -#: src/Model/Behavior/RegisterBehavior.php:107 -msgid "User not found for the given token and email." +#: ./vendor/cakedc/users/src/Controller/Traits/SimpleCrudTrait.php:131 +msgid "The {0} could not be deleted" msgstr "" -#: src/Model/Behavior/RegisterBehavior.php:110 -msgid "Token has already expired user with no token" +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:51 +msgid "User account validated successfully" msgstr "" -#: src/Model/Behavior/RegisterBehavior.php:167 -msgid "This field is required" +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:53 +msgid "User account could not be validated" msgstr "" -#: src/Model/Behavior/SocialAccountBehavior.php:100 -#: src/Model/Behavior/SocialAccountBehavior.php:130 -msgid "Account already validated" +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:56 +msgid "User already active" msgstr "" -#: src/Model/Behavior/SocialAccountBehavior.php:104 -#: src/Model/Behavior/SocialAccountBehavior.php:135 -msgid "Account not found for the given token and email." +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:62 +msgid "Reset password token was validated successfully" msgstr "" -#: src/Model/Behavior/SocialBehavior.php:85 -msgid "Unable to login user with reference {0}" +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:70 +msgid "Reset password token could not be validated" msgstr "" -#: src/Model/Behavior/SocialBehavior.php:136 -msgid "Email not present" +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:74 +msgid "Invalid validation type" msgstr "" -#: src/Model/Table/UsersTable.php:107 -msgid "Your password does not match your confirm password. Please try again" +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:77 +msgid "Invalid token or user account already validated" msgstr "" -#: src/Model/Table/UsersTable.php:201 -msgid "Username already exists" +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:84 +msgid "Token already expired" msgstr "" -#: src/Model/Table/UsersTable.php:207 -msgid "Email already exists" +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:117 +msgid "Token has been reset successfully. Please check your email." msgstr "" -#: src/Shell/UsersShell.php:46 -msgid "Utilities for CakeDC Users Plugin" +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:122 +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:131 +msgid "Token could not be reset" msgstr "" -#: src/Shell/UsersShell.php:48 -msgid "Activate an specific user" +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:127 +msgid "User {0} was not found" msgstr "" -#: src/Shell/UsersShell.php:51 -msgid "Add a new superadmin user for testing purposes" +#: ./vendor/cakedc/users/src/Controller/Traits/UserValidationTrait.php:129 +msgid "User {0} is already active" msgstr "" -#: src/Shell/UsersShell.php:54 -msgid "Add a new user" +#: ./vendor/cakedc/users/src/Controller/Traits/Webauthn2faTrait.php:55 +#: ./vendor/cakedc/users/src/Controller/Traits/Webauthn2faTrait.php:76 +msgid "User already has configured webauthn2fa" msgstr "" -#: src/Shell/UsersShell.php:57 -msgid "Change the role for an specific user" +#: ./vendor/cakedc/users/src/Controller/Traits/Webauthn2faTrait.php:80 +#: ./vendor/cakedc/users/src/Controller/Traits/Webauthn2faTrait.php:127 +msgid "Register error with webauthn for user id: {0}" msgstr "" -#: src/Shell/UsersShell.php:60 -msgid "Change the api token for an specific user" +#: ./vendor/cakedc/users/src/Identifier/PasswordLockout/LockoutHandler.php:155 +msgid "Config \"timeWindowInSeconds\" must be integer greater than 60" msgstr "" -#: src/Shell/UsersShell.php:63 -msgid "Deactivate an specific user" +#: ./vendor/cakedc/users/src/Identifier/PasswordLockout/LockoutHandler.php:167 +msgid "Config \"numberOfAttemptsFail\" must be integer greater or equal 0" msgstr "" -#: src/Shell/UsersShell.php:66 -msgid "Delete an specific user" +#: ./vendor/cakedc/users/src/Identifier/PasswordLockout/LockoutHandler.php:180 +msgid "Config \"lockoutTimeInSeconds\" must be integer greater than 60" msgstr "" -#: src/Shell/UsersShell.php:69 -msgid "Reset the password via email" +#: ./vendor/cakedc/users/src/Identifier/PasswordLockoutIdentifier.php:73 +msgid "Lockout handler has not been set." msgstr "" -#: src/Shell/UsersShell.php:72 -msgid "Reset the password for all users" +#: ./vendor/cakedc/users/src/Identifier/PasswordLockoutIdentifier.php:88 +msgid "Option `className` for lockout handler is not present." msgstr "" -#: src/Shell/UsersShell.php:75 -msgid "Reset the password for an specific user" +#: ./vendor/cakedc/users/src/Loader/AuthenticationServiceLoader.php:109 +msgid "Property {0}.className should be defined" msgstr "" -#: src/Shell/UsersShell.php:135 -#: src/Shell/UsersShell.php:161 -msgid "Please enter a password." +#: ./vendor/cakedc/users/src/Loader/LoginComponentLoader.php:31 +msgid "Username or password is incorrect" msgstr "" -#: src/Shell/UsersShell.php:139 -msgid "Password changed for all users" +#: ./vendor/cakedc/users/src/Loader/LoginComponentLoader.php:52 +msgid "Could not proceed with social account. Please try again" msgstr "" -#: src/Shell/UsersShell.php:140 -#: src/Shell/UsersShell.php:168 -msgid "New password: {0}" +#: ./vendor/cakedc/users/src/Loader/LoginComponentLoader.php:54 +msgid "Your user has not been validated yet. Please check your inbox for instructions" msgstr "" -#: src/Shell/UsersShell.php:158 -#: src/Shell/UsersShell.php:186 -#: src/Shell/UsersShell.php:214 -#: src/Shell/UsersShell.php:304 -#: src/Shell/UsersShell.php:403 -msgid "Please enter a username." +#: ./vendor/cakedc/users/src/Loader/LoginComponentLoader.php:58 +msgid "Your social account has not been validated yet. Please check your inbox for instructions" msgstr "" -#: src/Shell/UsersShell.php:167 -msgid "Password changed for user: {0}" +#: ./vendor/cakedc/users/src/Mailer/UsersMailer.php:36 +msgid "Your account validation link" msgstr "" -#: src/Shell/UsersShell.php:189 -msgid "Please enter a role." +#: ./vendor/cakedc/users/src/Mailer/UsersMailer.php:71 +msgid "{0}Your reset password link" msgstr "" -#: src/Shell/UsersShell.php:195 -msgid "Role changed for user: {0}" +#: ./vendor/cakedc/users/src/Mailer/UsersMailer.php:110 +msgid "{0}Your social account validation link" msgstr "" -#: src/Shell/UsersShell.php:196 -msgid "New role: {0}" +#: ./vendor/cakedc/users/src/Middleware/SocialAuthMiddleware.php:47 +#: ./vendor/cakedc/users/templates/Users/social_email.php:16 +msgid "Please enter your email" msgstr "" -#: src/Shell/UsersShell.php:217 -msgid "Please enter a token." +#: ./vendor/cakedc/users/src/Middleware/SocialAuthMiddleware.php:57 +msgid "Could not identify your account, please try again" msgstr "" -#: src/Shell/UsersShell.php:224 -msgid "User was not saved, check validation errors" +#: ./vendor/cakedc/users/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php:125 +msgid "Location = {0}" msgstr "" -#: src/Shell/UsersShell.php:229 -msgid "Api token changed for user: {0}" +#: ./vendor/cakedc/users/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php:129 +msgid "You are not authorized to access that location." msgstr "" -#: src/Shell/UsersShell.php:230 -msgid "New token: {0}" +#: ./vendor/cakedc/users/src/Model/Behavior/AuthFinderBehavior.php:50 +msgid "Missing 'username' in options data" msgstr "" -#: src/Shell/UsersShell.php:245 -msgid "User was activated: {0}" +#: ./vendor/cakedc/users/src/Model/Behavior/LinkSocialBehavior.php:50 +msgid "Social account already associated to another user" msgstr "" -#: src/Shell/UsersShell.php:260 -msgid "User was de-activated: {0}" +#: ./vendor/cakedc/users/src/Model/Behavior/PasswordBehavior.php:45 +msgid "Reference cannot be null" msgstr "" -#: src/Shell/UsersShell.php:272 -msgid "Please enter a username or email." +#: ./vendor/cakedc/users/src/Model/Behavior/PasswordBehavior.php:50 +msgid "Token expiration cannot be empty" msgstr "" -#: src/Shell/UsersShell.php:280 -msgid "Please ask the user to check the email to continue with password reset process" +#: ./vendor/cakedc/users/src/Model/Behavior/PasswordBehavior.php:56 +#: ./vendor/cakedc/users/src/Model/Behavior/PasswordBehavior.php:140 +msgid "User not found" msgstr "" -#: src/Shell/UsersShell.php:350 -msgid "Superuser added:" +#: ./vendor/cakedc/users/src/Model/Behavior/PasswordBehavior.php:60 +#: ./vendor/cakedc/users/src/Model/Behavior/RegisterBehavior.php:129 +msgid "User account already validated" msgstr "" -#: src/Shell/UsersShell.php:352 -msgid "User added:" +#: ./vendor/cakedc/users/src/Model/Behavior/PasswordBehavior.php:66 +msgid "User not active" msgstr "" -#: src/Shell/UsersShell.php:354 -msgid "Id: {0}" +#: ./vendor/cakedc/users/src/Model/Behavior/PasswordBehavior.php:145 +msgid "The current password does not match" msgstr "" -#: src/Shell/UsersShell.php:355 -msgid "Username: {0}" +#: ./vendor/cakedc/users/src/Model/Behavior/PasswordBehavior.php:148 +msgid "You cannot use the current password as the new one" msgstr "" -#: src/Shell/UsersShell.php:356 -msgid "Email: {0}" +#: ./vendor/cakedc/users/src/Model/Behavior/RegisterBehavior.php:107 +msgid "User not found for the given token and email." msgstr "" -#: src/Shell/UsersShell.php:357 -msgid "Role: {0}" +#: ./vendor/cakedc/users/src/Model/Behavior/RegisterBehavior.php:110 +msgid "Token has already expired user with no token" msgstr "" -#: src/Shell/UsersShell.php:358 -msgid "Password: {0}" +#: ./vendor/cakedc/users/src/Model/Behavior/RegisterBehavior.php:167 +msgid "This field is required" msgstr "" -#: src/Shell/UsersShell.php:360 -msgid "User could not be added:" +#: ./vendor/cakedc/users/src/Model/Behavior/SocialAccountBehavior.php:100 +#: ./vendor/cakedc/users/src/Model/Behavior/SocialAccountBehavior.php:130 +msgid "Account already validated" msgstr "" -#: src/Shell/UsersShell.php:363 -msgid "Field: {0} Error: {1}" +#: ./vendor/cakedc/users/src/Model/Behavior/SocialAccountBehavior.php:104 +#: ./vendor/cakedc/users/src/Model/Behavior/SocialAccountBehavior.php:135 +msgid "Account not found for the given token and email." msgstr "" -#: src/Shell/UsersShell.php:379 -msgid "The user was not found." +#: ./vendor/cakedc/users/src/Model/Behavior/SocialBehavior.php:93 +msgid "Unable to login user with reference {0}" msgstr "" -#: src/Shell/UsersShell.php:414 -msgid "The user {0} was not deleted. Please try again" +#: ./vendor/cakedc/users/src/Model/Behavior/SocialBehavior.php:144 +msgid "Email not present" msgstr "" -#: src/Shell/UsersShell.php:416 -msgid "The user {0} was deleted successfully" +#: ./vendor/cakedc/users/src/Model/Table/UsersTable.php:108 +msgid "Your password does not match your confirm password. Please try again" msgstr "" -#: src/View/Helper/UserHelper.php:50 +#: ./vendor/cakedc/users/src/Model/Table/UsersTable.php:202 +msgid "Username already exists" +msgstr "" + +#: ./vendor/cakedc/users/src/Model/Table/UsersTable.php:208 +msgid "Email already exists" +msgstr "" + +#: ./vendor/cakedc/users/src/View/Helper/UserHelper.php:49 msgid "Sign in with" msgstr "" -#: src/View/Helper/UserHelper.php:113 +#: ./vendor/cakedc/users/src/View/Helper/UserHelper.php:112 msgid "Logout" msgstr "" -#: src/View/Helper/UserHelper.php:134 -msgid "Welcome, {0}" +#: ./vendor/cakedc/users/src/View/Helper/UserHelper.php:195 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" msgstr "" -#: src/View/Helper/UserHelper.php:165 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +#: ./vendor/cakedc/users/src/View/Helper/UserHelper.php:213 +msgid "reCaptcha version is wrong. Please configure Users.reCaptcha.version as 2 or 3" msgstr "" -#: src/View/Helper/UserHelper.php:218 +#: ./vendor/cakedc/users/src/View/Helper/UserHelper.php:299 msgid "Connected with {0}" msgstr "" -#: src/View/Helper/UserHelper.php:223 +#: ./vendor/cakedc/users/src/View/Helper/UserHelper.php:304 msgid "Connect with {0}" msgstr "" -#: templates/Users/add.php:13 -#: templates/Users/edit.php:17 -#: templates/Users/index.php:13 -#: templates/Users/index.php:26 -#: templates/Users/view.php:15 +#: ./vendor/cakedc/users/src/Webauthn/AuthenticateAdapter.php:78 +msgid "Could not validate credential response for authentication" +msgstr "" + +#: ./vendor/cakedc/users/src/Webauthn/RegisterAdapter.php:84 +msgid "Could not credential response for registration" +msgstr "" + +#: ./vendor/cakedc/users/config/bootstrap.php:39 +msgid "Users plugin configuration key \"{0}\" was removed, please check migration guide https://github.com/CakeDC/users/blob/master/Docs/Documentation/Migration/8.x-9.0.md" +msgstr "" + +#: ./vendor/cakedc/users/config/users.php:88 +msgid "Empty password" +msgstr "" + +#: ./vendor/cakedc/users/config/users.php:89 +msgid "Too simple" +msgstr "" + +#: ./vendor/cakedc/users/config/users.php:90 +msgid "Simple" +msgstr "" + +#: ./vendor/cakedc/users/config/users.php:91 +msgid "That's OK" +msgstr "" + +#: ./vendor/cakedc/users/config/users.php:92 +msgid "Great password!" +msgstr "" + +#: ./vendor/cakedc/users/templates/Users/add.php:13 +#: ./vendor/cakedc/users/templates/Users/edit.php:17 +#: ./vendor/cakedc/users/templates/Users/index.php:13 +#: ./vendor/cakedc/users/templates/Users/index.php:26 +#: ./vendor/cakedc/users/templates/Users/view.php:15 msgid "Actions" msgstr "" -#: templates/Users/add.php:15 -#: templates/Users/edit.php:28 -#: templates/Users/view.php:23 +#: ./vendor/cakedc/users/templates/Users/add.php:15 +#: ./vendor/cakedc/users/templates/Users/edit.php:28 +#: ./vendor/cakedc/users/templates/Users/view.php:23 msgid "List Users" msgstr "" -#: templates/Users/add.php:21 -#: templates/Users/register.php:18 +#: ./vendor/cakedc/users/templates/Users/add.php:21 +#: ./vendor/cakedc/users/templates/Users/register.php:18 msgid "Add User" msgstr "" -#: templates/Users/add.php:23 -#: templates/Users/edit.php:36 -#: templates/Users/index.php:22 -#: templates/Users/login.php:20 -#: templates/Users/profile.php:30 -#: templates/Users/register.php:20 -#: templates/Users/view.php:33 +#: ./vendor/cakedc/users/templates/Users/add.php:23 +#: ./vendor/cakedc/users/templates/Users/edit.php:36 +#: ./vendor/cakedc/users/templates/Users/index.php:22 +#: ./vendor/cakedc/users/templates/Users/login.php:20 +#: ./vendor/cakedc/users/templates/Users/profile.php:31 +#: ./vendor/cakedc/users/templates/Users/register.php:20 +#: ./vendor/cakedc/users/templates/Users/view.php:33 msgid "Username" msgstr "" -#: templates/Users/add.php:24 -#: templates/Users/edit.php:37 -#: templates/Users/index.php:23 -#: templates/Users/profile.php:32 -#: templates/Users/register.php:21 -#: templates/Users/view.php:35 +#: ./vendor/cakedc/users/templates/Users/add.php:24 +#: ./vendor/cakedc/users/templates/Users/edit.php:37 +#: ./vendor/cakedc/users/templates/Users/index.php:23 +#: ./vendor/cakedc/users/templates/Users/profile.php:33 +#: ./vendor/cakedc/users/templates/Users/register.php:21 +#: ./vendor/cakedc/users/templates/Users/view.php:35 msgid "Email" msgstr "" -#: templates/Users/add.php:25 -#: templates/Users/login.php:21 -#: templates/Users/register.php:22 +#: ./vendor/cakedc/users/templates/Users/add.php:25 +#: ./vendor/cakedc/users/templates/Users/login.php:21 +#: ./vendor/cakedc/users/templates/Users/register.php:22 msgid "Password" msgstr "" -#: templates/Users/add.php:26 -#: templates/Users/edit.php:38 -#: templates/Users/index.php:24 -#: templates/Users/register.php:28 +#: ./vendor/cakedc/users/templates/Users/add.php:26 +#: ./vendor/cakedc/users/templates/Users/edit.php:38 +#: ./vendor/cakedc/users/templates/Users/index.php:24 +#: ./vendor/cakedc/users/templates/Users/register.php:31 msgid "First name" msgstr "" -#: templates/Users/add.php:27 -#: templates/Users/edit.php:39 -#: templates/Users/index.php:25 -#: templates/Users/register.php:29 +#: ./vendor/cakedc/users/templates/Users/add.php:27 +#: ./vendor/cakedc/users/templates/Users/edit.php:39 +#: ./vendor/cakedc/users/templates/Users/index.php:25 +#: ./vendor/cakedc/users/templates/Users/register.php:32 msgid "Last name" msgstr "" -#: templates/Users/add.php:30 -#: templates/Users/edit.php:54 -#: templates/Users/view.php:49 -#: templates/Users/view.php:74 +#: ./vendor/cakedc/users/templates/Users/add.php:30 +#: ./vendor/cakedc/users/templates/Users/edit.php:54 +#: ./vendor/cakedc/users/templates/Users/view.php:49 +#: ./vendor/cakedc/users/templates/Users/view.php:74 msgid "Active" msgstr "" -#: templates/Users/add.php:34 -#: templates/Users/change_password.php:25 -#: templates/Users/edit.php:58 -#: templates/Users/register.php:38 -#: templates/Users/request_reset_password.php:23 -#: templates/Users/resend_token_validation.php:20 -#: templates/Users/social_email.php:19 +#: ./vendor/cakedc/users/templates/Users/add.php:34 +#: ./vendor/cakedc/users/templates/Users/change_password.php:29 +#: ./vendor/cakedc/users/templates/Users/edit.php:58 +#: ./vendor/cakedc/users/templates/Users/register.php:41 +#: ./vendor/cakedc/users/templates/Users/request_reset_password.php:23 +#: ./vendor/cakedc/users/templates/Users/resend_token_validation.php:20 +#: ./vendor/cakedc/users/templates/Users/social_email.php:19 msgid "Submit" msgstr "" -#: templates/Users/change_password.php:5 +#: ./vendor/cakedc/users/templates/Users/change_password.php:5 msgid "Please enter the new password" msgstr "" -#: templates/Users/change_password.php:10 +#: ./vendor/cakedc/users/templates/Users/change_password.php:10 msgid "Current password" msgstr "" -#: templates/Users/change_password.php:16 +#: ./vendor/cakedc/users/templates/Users/change_password.php:17 msgid "New password" msgstr "" -#: templates/Users/change_password.php:21 -#: templates/Users/register.php:26 +#: ./vendor/cakedc/users/templates/Users/change_password.php:25 +#: ./vendor/cakedc/users/templates/Users/register.php:29 msgid "Confirm password" msgstr "" -#: templates/Users/edit.php:22 -#: templates/Users/index.php:40 +#: ./vendor/cakedc/users/templates/Users/edit.php:22 +#: ./vendor/cakedc/users/templates/Users/index.php:40 msgid "Delete" msgstr "" -#: templates/Users/edit.php:24 -#: templates/Users/index.php:40 -#: templates/Users/view.php:21 +#: ./vendor/cakedc/users/templates/Users/edit.php:24 +#: ./vendor/cakedc/users/templates/Users/index.php:40 +#: ./vendor/cakedc/users/templates/Users/view.php:21 msgid "Are you sure you want to delete # {0}?" msgstr "" -#: templates/Users/edit.php:34 -#: templates/Users/view.php:17 +#: ./vendor/cakedc/users/templates/Users/edit.php:34 +#: ./vendor/cakedc/users/templates/Users/view.php:17 msgid "Edit User" msgstr "" -#: templates/Users/edit.php:40 -#: templates/Users/view.php:43 +#: ./vendor/cakedc/users/templates/Users/edit.php:40 +#: ./vendor/cakedc/users/templates/Users/view.php:43 msgid "Token" msgstr "" -#: templates/Users/edit.php:42 +#: ./vendor/cakedc/users/templates/Users/edit.php:42 msgid "Token expires" msgstr "" -#: templates/Users/edit.php:45 +#: ./vendor/cakedc/users/templates/Users/edit.php:45 msgid "API token" msgstr "" -#: templates/Users/edit.php:48 +#: ./vendor/cakedc/users/templates/Users/edit.php:48 msgid "Activation date" msgstr "" -#: templates/Users/edit.php:51 +#: ./vendor/cakedc/users/templates/Users/edit.php:51 msgid "TOS date" msgstr "" -#: templates/Users/edit.php:64 +#: ./vendor/cakedc/users/templates/Users/edit.php:64 msgid "Reset Google Authenticator Token" msgstr "" -#: templates/Users/edit.php:70 +#: ./vendor/cakedc/users/templates/Users/edit.php:70 msgid "Are you sure you want to reset token for user \"{0}\"?" msgstr "" -#: templates/Users/index.php:15 +#: ./vendor/cakedc/users/templates/Users/index.php:15 msgid "New {0}" msgstr "" -#: templates/Users/index.php:37 +#: ./vendor/cakedc/users/templates/Users/index.php:37 msgid "View" msgstr "" -#: templates/Users/index.php:38 +#: ./vendor/cakedc/users/templates/Users/index.php:38 msgid "Change password" msgstr "" -#: templates/Users/index.php:39 +#: ./vendor/cakedc/users/templates/Users/index.php:39 msgid "Edit" msgstr "" -#: templates/Users/index.php:49 +#: ./vendor/cakedc/users/templates/Users/index.php:49 msgid "previous" msgstr "" -#: templates/Users/index.php:51 +#: ./vendor/cakedc/users/templates/Users/index.php:51 msgid "next" msgstr "" -#: templates/Users/login.php:19 +#: ./vendor/cakedc/users/templates/Users/login.php:19 msgid "Please enter your username and password" msgstr "" -#: templates/Users/login.php:29 +#: ./vendor/cakedc/users/templates/Users/login.php:29 msgid "Remember me" msgstr "" -#: templates/Users/login.php:37 +#: ./vendor/cakedc/users/templates/Users/login.php:37 msgid "Register" msgstr "" -#: templates/Users/login.php:43 +#: ./vendor/cakedc/users/templates/Users/login.php:43 msgid "Reset Password" msgstr "" -#: templates/Users/login.php:48 +#: ./vendor/cakedc/users/templates/Users/login.php:48 msgid "Login" msgstr "" -#: templates/Users/profile.php:21 +#: ./vendor/cakedc/users/templates/Users/profile.php:21 msgid "{0} {1}" msgstr "" -#: templates/Users/profile.php:27 +#: ./vendor/cakedc/users/templates/Users/profile.php:27 msgid "Change Password" msgstr "" -#: templates/Users/profile.php:38 -#: templates/Users/view.php:68 +#: ./vendor/cakedc/users/templates/Users/profile.php:39 +#: ./vendor/cakedc/users/templates/Users/view.php:68 msgid "Social Accounts" msgstr "" -#: templates/Users/profile.php:42 -#: templates/Users/view.php:73 +#: ./vendor/cakedc/users/templates/Users/profile.php:43 +#: ./vendor/cakedc/users/templates/Users/view.php:73 msgid "Avatar" msgstr "" -#: templates/Users/profile.php:43 -#: templates/Users/view.php:72 +#: ./vendor/cakedc/users/templates/Users/profile.php:44 +#: ./vendor/cakedc/users/templates/Users/view.php:72 msgid "Provider" msgstr "" -#: templates/Users/profile.php:44 +#: ./vendor/cakedc/users/templates/Users/profile.php:45 msgid "Link" msgstr "" -#: templates/Users/profile.php:51 +#: ./vendor/cakedc/users/templates/Users/profile.php:52 msgid "Link to {0}" msgstr "" -#: templates/Users/register.php:31 +#: ./vendor/cakedc/users/templates/Users/register.php:34 msgid "Accept TOS conditions?" msgstr "" -#: templates/Users/request_reset_password.php:20 +#: ./vendor/cakedc/users/templates/Users/request_reset_password.php:20 msgid "Please enter your email or username to reset your password" msgstr "" -#: templates/Users/resend_token_validation.php:15 +#: ./vendor/cakedc/users/templates/Users/resend_token_validation.php:15 msgid "Resend Validation email" msgstr "" -#: templates/Users/resend_token_validation.php:17 +#: ./vendor/cakedc/users/templates/Users/resend_token_validation.php:17 msgid "Email or username" msgstr "" -#: templates/Users/u2f_authenticate.php:22 -#: templates/Users/webauthn2fa.php:25 -msgid "Verify your registered yubico key" -msgstr "" - -#: templates/Users/u2f_authenticate.php:23 -#: templates/Users/u2f_register.php:23 -#: templates/Users/webauthn2fa.php:20 -#: templates/Users/webauthn2fa.php:26 -msgid "Please insert and tap your yubico key" -msgstr "" - -#: templates/Users/u2f_authenticate.php:24 -#: templates/Users/webauthn2fa.php:27 -msgid "You can now finish the authentication process using the registered device." -msgstr "" - -#: templates/Users/u2f_authenticate.php:25 -#: templates/Users/webauthn2fa.php:22 -#: templates/Users/webauthn2fa.php:28 -msgid "When the YubiKey starts blinking, press the golden disc to activate it. Depending on the web browser you might need to confirm the use of extended information from the YubiKey." -msgstr "" - -#: templates/Users/u2f_authenticate.php:27 -#: templates/Users/u2f_register.php:27 -#: templates/Users/webauthn2fa.php:31 -msgid "Reload" -msgstr "" - -#: templates/Users/u2f_authenticate.php:51 -#: templates/Users/u2f_register.php:56 -msgid "Yubico key check has failed, please try again" -msgstr "" - -#: templates/Users/u2f_register.php:22 -#: templates/Users/webauthn2fa.php:19 -msgid "Registering your yubico key" -msgstr "" - -#: templates/Users/verify.php:13 +#: ./vendor/cakedc/users/templates/Users/verify.php:13 msgid "Verification Code" msgstr "" -#: templates/Users/verify.php:15 +#: ./vendor/cakedc/users/templates/Users/verify.php:15 msgid " Verify" msgstr "" -#: templates/Users/view.php:19 +#: ./vendor/cakedc/users/templates/Users/view.php:19 msgid "Delete User" msgstr "" -#: templates/Users/view.php:24 +#: ./vendor/cakedc/users/templates/Users/view.php:24 msgid "New User" msgstr "" -#: templates/Users/view.php:31 +#: ./vendor/cakedc/users/templates/Users/view.php:31 msgid "Id" msgstr "" -#: templates/Users/view.php:37 +#: ./vendor/cakedc/users/templates/Users/view.php:37 msgid "First Name" msgstr "" -#: templates/Users/view.php:39 +#: ./vendor/cakedc/users/templates/Users/view.php:39 msgid "Last Name" msgstr "" -#: templates/Users/view.php:41 +#: ./vendor/cakedc/users/templates/Users/view.php:41 msgid "Role" msgstr "" -#: templates/Users/view.php:45 +#: ./vendor/cakedc/users/templates/Users/view.php:45 msgid "Api Token" msgstr "" -#: templates/Users/view.php:53 +#: ./vendor/cakedc/users/templates/Users/view.php:53 msgid "Token Expires" msgstr "" -#: templates/Users/view.php:55 +#: ./vendor/cakedc/users/templates/Users/view.php:55 msgid "Activation Date" msgstr "" -#: templates/Users/view.php:57 +#: ./vendor/cakedc/users/templates/Users/view.php:57 msgid "Tos Date" msgstr "" -#: templates/Users/view.php:59 -#: templates/Users/view.php:75 +#: ./vendor/cakedc/users/templates/Users/view.php:59 +#: ./vendor/cakedc/users/templates/Users/view.php:75 msgid "Created" msgstr "" -#: templates/Users/view.php:61 -#: templates/Users/view.php:76 +#: ./vendor/cakedc/users/templates/Users/view.php:61 +#: ./vendor/cakedc/users/templates/Users/view.php:76 msgid "Modified" msgstr "" -#: templates/Users/webauthn2fa.php:8 +#: ./vendor/cakedc/users/templates/Users/webauthn2fa.php:8 msgid "Two-factor authentication" msgstr "" -#: templates/Users/webauthn2fa.php:21 +#: ./vendor/cakedc/users/templates/Users/webauthn2fa.php:19 +msgid "Registering your yubico key" +msgstr "" + +#: ./vendor/cakedc/users/templates/Users/webauthn2fa.php:20 +#: ./vendor/cakedc/users/templates/Users/webauthn2fa.php:26 +msgid "Please insert and tap your yubico key" +msgstr "" + +#: ./vendor/cakedc/users/templates/Users/webauthn2fa.php:21 msgid "In order to enable your YubiKey the first step is to perform a registration." msgstr "" -#: templates/email/html/reset_password.php:14 -#: templates/email/html/social_account_validation.php:14 -#: templates/email/html/validation.php:13 -#: templates/email/text/reset_password.php:12 -#: templates/email/text/social_account_validation.php:12 -#: templates/email/text/validation.php:12 +#: ./vendor/cakedc/users/templates/Users/webauthn2fa.php:22 +#: ./vendor/cakedc/users/templates/Users/webauthn2fa.php:28 +msgid "When the YubiKey starts blinking, press the golden disc to activate it. Depending on the web browser you might need to confirm the use of extended information from the YubiKey." +msgstr "" + +#: ./vendor/cakedc/users/templates/Users/webauthn2fa.php:25 +msgid "Verify your registered yubico key" +msgstr "" + +#: ./vendor/cakedc/users/templates/Users/webauthn2fa.php:27 +msgid "You can now finish the authentication process using the registered device." +msgstr "" + +#: ./vendor/cakedc/users/templates/Users/webauthn2fa.php:31 +msgid "Reload" +msgstr "" + +#: ./vendor/cakedc/users/templates/email/html/reset_password.php:14 +#: ./vendor/cakedc/users/templates/email/html/social_account_validation.php:14 +#: ./vendor/cakedc/users/templates/email/html/validation.php:13 +#: ./vendor/cakedc/users/templates/email/text/reset_password.php:12 +#: ./vendor/cakedc/users/templates/email/text/social_account_validation.php:12 +#: ./vendor/cakedc/users/templates/email/text/validation.php:12 msgid "Hi {0}" msgstr "" -#: templates/email/html/reset_password.php:17 +#: ./vendor/cakedc/users/templates/email/html/reset_password.php:17 msgid "Reset your password here" msgstr "" -#: templates/email/html/reset_password.php:20 -#: templates/email/html/social_account_validation.php:23 -#: templates/email/html/validation.php:19 +#: ./vendor/cakedc/users/templates/email/html/reset_password.php:20 +#: ./vendor/cakedc/users/templates/email/html/social_account_validation.php:23 +#: ./vendor/cakedc/users/templates/email/html/validation.php:19 msgid "If the link is not correctly displayed, please copy the following address in your web browser {0}" msgstr "" -#: templates/email/html/reset_password.php:27 -#: templates/email/html/social_account_validation.php:30 -#: templates/email/html/validation.php:26 -#: templates/email/text/reset_password.php:20 -#: templates/email/text/social_account_validation.php:20 -#: templates/email/text/validation.php:20 +#: ./vendor/cakedc/users/templates/email/html/reset_password.php:27 +#: ./vendor/cakedc/users/templates/email/html/social_account_validation.php:30 +#: ./vendor/cakedc/users/templates/email/html/validation.php:26 +#: ./vendor/cakedc/users/templates/email/text/reset_password.php:20 +#: ./vendor/cakedc/users/templates/email/text/social_account_validation.php:20 +#: ./vendor/cakedc/users/templates/email/text/validation.php:20 msgid "Thank you" msgstr "" -#: templates/email/html/social_account_validation.php:18 +#: ./vendor/cakedc/users/templates/email/html/social_account_validation.php:18 msgid "Activate your social login here" msgstr "" -#: templates/email/html/validation.php:16 +#: ./vendor/cakedc/users/templates/email/html/validation.php:16 msgid "Activate your account here" msgstr "" -#: templates/email/text/reset_password.php:14 -#: templates/email/text/validation.php:14 +#: ./vendor/cakedc/users/templates/email/text/reset_password.php:14 +#: ./vendor/cakedc/users/templates/email/text/validation.php:14 msgid "Please copy the following address in your web browser {0}" msgstr "" -#: templates/email/text/social_account_validation.php:14 +#: ./vendor/cakedc/users/templates/email/text/social_account_validation.php:14 msgid "Please copy the following address in your web browser to activate your social login {0}" msgstr "" diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index edf071777..9625429de 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -166,7 +166,10 @@ public function requestResetPassword() 'type' => 'password', ]); if ($resetUser) { - $msg = __d('cake_d_c/users', 'If the account is valid, the system will send an instructional email to the address on record.'); + $msg = __d( + 'cake_d_c/users', + 'If the account is valid, the system will send an instructional email to the address on record.' + ); $this->Flash->success($msg); } else { $msg = __d('cake_d_c/users', 'There was an error please contact Administrator'); @@ -175,7 +178,10 @@ public function requestResetPassword() return $this->redirect(['action' => 'login']); } catch (UserNotFoundException | UserNotActiveException $exception) { - $msg = __d('cake_d_c/users', 'If the account is valid, the system will send an instructional email to the address on record.'); + $msg = __d( + 'cake_d_c/users', + 'If the account is valid, the system will send an instructional email to the address on record.' + ); $this->Flash->success($msg); } catch (Exception $exception) { $msg = __d('cake_d_c/users', 'There was an error please contact Administrator'); diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 2c7068473..6a8b257c8 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -77,7 +77,7 @@ public function register() } elseif (Configure::read('Users.Registration.showVerboseError') && count($errors) > 0) { $this->set(compact('user')); foreach ($errors as $error) { - $this->Flash->error(__($error)); + $this->Flash->error($error); } return; @@ -109,7 +109,7 @@ public function register() $errors = \collection($user->getErrors())->unfold()->toArray(); if (!$userSaved && Configure::read('Users.Registration.showVerboseError') && count($errors) > 0) { foreach ($errors as $error) { - $this->Flash->error(__($error)); + $this->Flash->error($error); } return; diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index bbe594ca4..1c565dc04 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -43,7 +43,10 @@ public function validate($type = null, $token = null) try { $result = $this->getUsersTable()->validate($token, 'activateUser'); if ($result) { - $event = $this->dispatchEvent(Plugin::EVENT_AFTER_EMAIL_TOKEN_VALIDATION, ['user' => $result]); + $event = $this->dispatchEvent( + Plugin::EVENT_AFTER_EMAIL_TOKEN_VALIDATION, + ['user' => $result] + ); $eventResult = $event->getResult(); if (!empty($eventResult) && is_array($eventResult)) { return $this->redirect($eventResult); diff --git a/src/Identifier/PasswordLockout/LockoutHandler.php b/src/Identifier/PasswordLockout/LockoutHandler.php index 5fc0180ce..596f58d4f 100644 --- a/src/Identifier/PasswordLockout/LockoutHandler.php +++ b/src/Identifier/PasswordLockout/LockoutHandler.php @@ -14,10 +14,10 @@ namespace CakeDC\Users\Identifier\PasswordLockout; use Cake\Core\InstanceConfigTrait; +use Cake\Datasource\EntityInterface; use Cake\I18n\DateTime; use Cake\ORM\Locator\LocatorAwareTrait; use Cake\ORM\Query\SelectQuery; -use CakeDC\Users\Model\Entity\FailedPasswordAttempt; class LockoutHandler implements LockoutHandlerInterface { @@ -36,6 +36,7 @@ class LockoutHandler implements LockoutHandlerInterface 'failedPasswordAttemptsModel' => 'CakeDC/Users.FailedPasswordAttempts', 'userLockoutField' => 'lockout_time', 'usersModel' => 'Users', + 'userForeignKeyField' => 'user_id', ]; /** @@ -73,9 +74,9 @@ public function isUnlocked(\ArrayAccess|array $identity): bool $lastAttempt = $this->getLastAttempt($identity['id'], $timeWindow); $this->getTableLocator() ->get($this->getConfig('usersModel')) - ->updateAll([$lockoutField => $lastAttempt->created], ['id' => $identity['id']]); + ->updateAll([$lockoutField => $lastAttempt->get('created')], ['id' => $identity['id']]); - return $this->checkLockoutTime($lastAttempt->created); + return $this->checkLockoutTime($lastAttempt->get('created')); } /** @@ -86,7 +87,7 @@ public function newFail(string|int $id): void { $timeWindow = $this->getTimeWindow(); $Table = $this->getTable(); - $entity = $Table->newEntity(['user_id' => $id]); + $entity = $Table->newEntity([$this->getConfig('userForeignKeyField') => $id]); $Table->saveOrFail($entity); $Table->deleteAll($Table->query()->newExpr()->lt('created', $timeWindow)); } @@ -96,7 +97,7 @@ public function newFail(string|int $id): void */ protected function getTable(): \Cake\ORM\Table { - return $this->getTableLocator()->get('CakeDC/Users.FailedPasswordAttempts'); + return $this->getTableLocator()->get($this->getConfig('failedPasswordAttemptsModel')); } /** @@ -112,9 +113,9 @@ protected function getAttemptsCount(string|int $id, DateTime $timeWindow): int /** * @param string|int $id * @param \Cake\I18n\DateTime $timeWindow - * @return \CakeDC\Users\Model\Entity\FailedPasswordAttempt + * @return \Cake\Datasource\EntityInterface */ - protected function getLastAttempt(int|string $id, DateTime $timeWindow): FailedPasswordAttempt + protected function getLastAttempt(int|string $id, DateTime $timeWindow): EntityInterface { /** * @var \CakeDC\Users\Model\Entity\FailedPasswordAttempt $attempt @@ -135,7 +136,7 @@ protected function getAttemptsQuery(int|string $id, DateTime $timeWindow): Selec return $query ->where([ - 'user_id' => $id, + $this->getConfig('userForeignKeyField') => $id, $query->newExpr()->gte('created', $timeWindow), ]) ->orderByDesc('created'); @@ -151,7 +152,12 @@ protected function getTimeWindow(): DateTime return (new DateTime())->subSeconds($timeWindow); } - throw new \UnexpectedValueException(__d('cake_d_c/users', 'Config "timeWindowInSeconds" must be integer greater than 60')); + throw new \UnexpectedValueException( + __d( + 'cake_d_c/users', + 'Config "timeWindowInSeconds" must be integer greater than 60' + ) + ); } /** @@ -163,7 +169,12 @@ protected function getNumberOfAttemptsFail(): int if (is_int($number) && $number >= 1) { return $number; } - throw new \UnexpectedValueException(__d('cake_d_c/users', 'Config "numberOfAttemptsFail" must be integer greater or equal 0')); + throw new \UnexpectedValueException( + __d( + 'cake_d_c/users', + 'Config "numberOfAttemptsFail" must be integer greater or equal 0' + ) + ); } /** @@ -176,7 +187,12 @@ protected function getLockoutTime(): int return $lockTime; } - throw new \UnexpectedValueException(__d('cake_d_c/users', 'Config "lockoutTimeInSeconds" must be integer greater than 60')); + throw new \UnexpectedValueException( + __d( + 'cake_d_c/users', + 'Config "lockoutTimeInSeconds" must be integer greater than 60' + ) + ); } /** diff --git a/src/Identifier/PasswordLockoutIdentifier.php b/src/Identifier/PasswordLockoutIdentifier.php index 2157dc812..c1fbc3360 100644 --- a/src/Identifier/PasswordLockoutIdentifier.php +++ b/src/Identifier/PasswordLockoutIdentifier.php @@ -85,7 +85,12 @@ protected function buildLockoutHandler(array|string $config): LockoutHandlerInte ]; } if (!isset($config['className'])) { - throw new \InvalidArgumentException(__d('cake_d_c/users', 'Option `className` for lockout handler is not present.')); + throw new \InvalidArgumentException( + __d( + 'cake_d_c/users', + 'Option `className` for lockout handler is not present.' + ) + ); } $className = $config['className']; diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 10408a060..a0a84650d 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -38,7 +38,11 @@ class SocialAccountBehavior extends Behavior public function initialize(array $config): void { parent::initialize($config); - $this->_table->belongsTo('Users')->setForeignKey('user_id')->setJoinType('INNER')->setClassName(Configure::read('Users.table')); + $this->_table + ->belongsTo('Users') + ->setForeignKey('user_id') + ->setJoinType('INNER') + ->setClassName(Configure::read('Users.table')); } /** diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index cc29bc3cb..2c0e982c8 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -16,6 +16,7 @@ use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Event\EventDispatcherTrait; +use Cake\ORM\Query\SelectQuery; use Cake\Utility\Hash; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; @@ -138,12 +139,11 @@ protected function _createSocialUser($data, $options = []) $useEmail = $options['use_email'] ?? null; $validateEmail = (bool)($options['validate_email'] ?? null); $tokenExpiration = $options['token_expiration'] ?? null; - $existingUser = null; $email = $data['email'] ?? null; if ($useEmail && empty($email)) { throw new MissingEmailException(__d('cake_d_c/users', 'Email not present')); } else { - $existingUser = $this->_table->find('existingForSocialLogin', options: ['email' => $email])->first(); + $existingUser = $this->_table->find('existingForSocialLogin', email: $email)->first(); } $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); @@ -230,7 +230,10 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail if ( $useEmail && empty($dataValidated) || - ($this->validateSocialAccount && !Configure::read('OAuth.providers.' . $data['provider'] . '.skipSocialAccountValidation')) + ( + $this->validateSocialAccount && + !Configure::read('OAuth.providers.' . $data['provider'] . '.skipSocialAccountValidation') + ) ) { $accountData['active'] = 0; } @@ -273,12 +276,11 @@ public function generateUniqueUsername($username) * Prepare a query to retrieve existing entity for social login * * @param \Cake\ORM\Query\SelectQuery $query The base query. - * @param array $options Find options with email key. + * @param string|null $email Find options with email key. * @return \Cake\ORM\Query\SelectQuery */ - public function findExistingForSocialLogin(\Cake\ORM\Query\SelectQuery $query, array $options) + public function findExistingForSocialLogin(SelectQuery $query, ?string $email = null): SelectQuery { - $email = $options['email'] ?? null; if (!$email) { return $query->where('1 != 1'); } diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 353b43cfd..5f176492e 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -197,13 +197,13 @@ public function validationRegister(Validator $validator) */ public function buildRules(RulesChecker $rules): RulesChecker { - $rules->add($rules->isUnique(['username']), '_isUnique', [ + $rules->add($rules->isUnique(['username']), '_isUniqueUsername', [ 'errorField' => 'username', 'message' => __d('cake_d_c/users', 'Username already exists'), ]); if ($this->isValidateEmail) { - $rules->add($rules->isUnique(['email']), '_isUnique', [ + $rules->add($rules->isUnique(['email']), '_isUniqueEmail', [ 'errorField' => 'email', 'message' => __d('cake_d_c/users', 'Email already exists'), ]); diff --git a/src/Plugin.php b/src/Plugin.php index 833a029cc..9c2ae5949 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -48,7 +48,8 @@ class Plugin extends BasePlugin public const EVENT_AFTER_RESEND_TOKEN_VALIDATION = 'Users.Global.afterResendTokenValidation'; public const EVENT_AFTER_EMAIL_TOKEN_VALIDATION = 'Users.Global.afterEmailTokenValidation'; - public const DEPRECATED_MESSAGE_U2F = 'U2F is no longer supported by chrome, we suggest using Webauthn as a replacement'; + public const DEPRECATED_MESSAGE_U2F = + 'U2F is no longer supported by chrome, we suggest using Webauthn as a replacement'; /** * @inheritDoc diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 691ec0fce..faf32bae4 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -18,6 +18,7 @@ use Cake\Utility\Inflector; use Cake\View\Helper; use CakeDC\Users\Utility\UsersUrl; +use InvalidArgumentException; /** * User helper @@ -42,7 +43,7 @@ class UserHelper extends Helper * @param array $options options * @return string */ - public function socialLogin($name, $options = []) + public function socialLogin(string $name, array $options = []): string { if (empty($options['label'])) { $options['label'] = __d('cake_d_c/users', 'Sign in with'); @@ -74,7 +75,7 @@ public function socialLogin($name, $options = []) * @param array $providerOptions Provider link options. * @return array Links to Social Login Urls */ - public function socialLoginList(array $providerOptions = []) + public function socialLoginList(array $providerOptions = []): array { if (!Configure::read('Users.Social.login')) { return []; @@ -105,7 +106,7 @@ public function socialLoginList(array $providerOptions = []) * @param array $options Array with option data. * @return string */ - public function logout($message = null, $options = []) + public function logout(?string $message = null, array $options = []): string { $url = UsersUrl::actionUrl('logout'); $title = empty($message) ? __d('cake_d_c/users', 'Logout') : $message; @@ -118,7 +119,7 @@ public function logout($message = null, $options = []) * * @return string|null */ - public function welcome() + public function welcome(): ?string { $identity = $this->getView()->getRequest()->getAttribute('identity'); if (!$identity) { @@ -143,19 +144,55 @@ public function welcome() * * @return void */ - public function addReCaptchaScript() + public function addReCaptchaScript(): void { $this->Html->script('https://www.google.com/recaptcha/api.js', [ 'block' => 'script', ]); } + /** + * @return void + */ + public function addPasswordMeterScript(): void + { + $this->Html->script('CakeDC/Users.pswmeter', [ + 'block' => 'script', + ]); + } + + /** + * @return string + */ + public function addPasswordMeter(): string + { + $this->addPasswordMeterScript(); + $requiredScore = Configure::read('Users.passwordMeter.requiredScore', 3); + $messagesList = json_encode( + Configure::read( + 'Users.passwordMeter.messagesList', + ['Empty password', 'Too simple', 'Simple', 'That\'s OK', 'Great password!'] + ) + ); + $pswMinLength = Configure::read('Users.passwordMinLength', 8); + $showMessage = Configure::read('Users.passwordMeter.showMessage', true) ? 'true' : 'false'; + $script = $this->Html->scriptBlock(" + const requiredScore = $requiredScore; + const messagesList = $messagesList; + const pswMinLength = $pswMinLength; + const showMessage = $showMessage; + ", ['defer' => true]); + + return $this->Html->tag('div', '', ['id' => 'pswmeter']) . + $this->Html->tag('div', '', ['id' => 'pswmeter-message']) . $script; + } + /** * Add reCaptcha to the form * * @return mixed */ - public function addReCaptcha() + public function addReCaptcha(): mixed { if (!Configure::read('Users.reCaptcha.key')) { return $this->Html->tag( @@ -167,10 +204,29 @@ public function addReCaptcha() ); } $this->addReCaptchaScript(); - try { - $this->Form->unlockField('g-recaptcha-response'); - } catch (\Exception $e) { + $version = Configure::read('Users.reCaptcha.version', 2); + $method = "addReCaptchaV$version"; + if (method_exists($this, $method)) { + try { + $this->Form->unlockField('g-recaptcha-response'); + } catch (\Exception $e) { + } + + return $this->{$method}(); } + throw new InvalidArgumentException( + __d('cake_d_c/users', 'reCaptcha version is wrong. Please configure Users.reCaptcha.version as 2 or 3') + ); + } + + /** + * Add required element for reCaptcha v2 + * + * @return string + */ + private function addReCaptchaV2(): string + { + deprecationWarning('14.2.0', 'reCaptcha version 3 will be used as default in version 15.0.0'); return $this->Html->tag('div', '', [ 'class' => 'g-recaptcha', @@ -181,6 +237,38 @@ public function addReCaptcha() ]); } + /** + * Add required script for reCaptcha v3 + */ + private function addReCaptchaV3(): void + { + $this->Html->script('CakeDC/Users.reCaptchaV3', [ + 'block' => 'script', + ]); + } + + /** + * Add required options for reCaptcha v3 + * + * @param string $title + * @param array $options + * @return string + */ + public function button(string $title, array $options = []): string + { + $key = Configure::read('Users.reCaptcha.key'); + if ($key && Configure::read('Users.reCaptcha.version', 2) === 3) { + $options = array_merge($options, [ + 'class' => 'g-recaptcha', + 'data-sitekey' => $key, + 'data-callback' => 'onSubmit', + 'data-action' => 'submit', + ]); + } + + return $this->Form->button($title, $options); + } + /** * Generate a link if the target url is authorized for the logged in user * @@ -190,7 +278,7 @@ public function addReCaptcha() * @param array $options Array with option data. * @return string */ - public function link($title, $url = null, array $options = []) + public function link(string $title, array|string|null $url = null, array $options = []): string { trigger_error( 'UserHelper::link() deprecated since 3.2.1. Use AuthLinkHelper::link() instead', @@ -208,7 +296,7 @@ public function link($title, $url = null, array $options = []) * @param bool $isConnected User is connected with this provider * @return string */ - public function socialConnectLink($name, $provider, $isConnected = false) + public function socialConnectLink(string $name, array $provider, bool $isConnected = false): string { $optionClass = $provider['options']['class'] ?? null; $linkClass = 'btn btn-social btn-' . strtolower($name) . ($optionClass ? ' ' . $optionClass : ''); @@ -236,7 +324,7 @@ public function socialConnectLink($name, $provider, $isConnected = false) * @param array $socialAccounts All social accounts connected by a user. * @return string */ - public function socialConnectLinkList($socialAccounts = []) + public function socialConnectLinkList(array $socialAccounts = []): string { if (!Configure::read('Users.Social.login')) { return ''; diff --git a/src/Webauthn/AuthenticateAdapter.php b/src/Webauthn/AuthenticateAdapter.php index 2adebbd61..082f45758 100644 --- a/src/Webauthn/AuthenticateAdapter.php +++ b/src/Webauthn/AuthenticateAdapter.php @@ -75,7 +75,12 @@ public function verifyResponse(): \Webauthn\PublicKeyCredentialSource ); } - throw new BadRequestException(__('Could not validate credential response for authentication')); + throw new BadRequestException( + __d( + 'cake_d_c/users', + 'Could not validate credential response for authentication' + ) + ); } /** diff --git a/src/Webauthn/BaseAdapter.php b/src/Webauthn/BaseAdapter.php index 1bf5a331e..ed6d815d6 100644 --- a/src/Webauthn/BaseAdapter.php +++ b/src/Webauthn/BaseAdapter.php @@ -115,8 +115,9 @@ public function hasCredential(): bool /** * @param \Webauthn\AttestationStatement\AttestationStatementSupportManager $attestationStatementSupportManager */ - public function setAttestationStatementSupportManager(AttestationStatementSupportManager $attestationStatementSupportManager): void - { + public function setAttestationStatementSupportManager( + AttestationStatementSupportManager $attestationStatementSupportManager + ): void { $this->attestationStatementSupportManager = $attestationStatementSupportManager; } diff --git a/src/Webauthn/PublicKeyCredentialLoader.php b/src/Webauthn/PublicKeyCredentialLoader.php index a0cf8113d..f23c3c4a7 100644 --- a/src/Webauthn/PublicKeyCredentialLoader.php +++ b/src/Webauthn/PublicKeyCredentialLoader.php @@ -26,14 +26,16 @@ public function loadArray(array $json): PublicKeyCredential isset($json['response']['clientDataJSON']) && is_string($json['response']['clientDataJSON']) ) { - $json['response']['clientDataJSON'] = Base64Utility::complyEncodedNoPadding($json['response']['clientDataJSON']); + $json['response']['clientDataJSON'] = + Base64Utility::complyEncodedNoPadding($json['response']['clientDataJSON']); } if ( isset($json['response']['authenticatorData']) && is_string($json['response']['authenticatorData']) ) { - $json['response']['authenticatorData'] = Base64Utility::complyEncodedNoPadding($json['response']['authenticatorData']); + $json['response']['authenticatorData'] = + Base64Utility::complyEncodedNoPadding($json['response']['authenticatorData']); } return parent::loadArray($json); diff --git a/src/Webauthn/RegisterAdapter.php b/src/Webauthn/RegisterAdapter.php index b6a00b546..ca883d8f4 100644 --- a/src/Webauthn/RegisterAdapter.php +++ b/src/Webauthn/RegisterAdapter.php @@ -81,7 +81,7 @@ public function verifyResponse(): \Webauthn\PublicKeyCredentialSource return $credential; } - throw new BadRequestException(__('Could not credential response for registration')); + throw new BadRequestException(__d('cake_d_c/users', 'Could not credential response for registration')); } /** diff --git a/templates/Users/change_password.php b/templates/Users/change_password.php index 7efba8f10..233343c27 100644 --- a/templates/Users/change_password.php +++ b/templates/Users/change_password.php @@ -13,8 +13,12 @@ Form->control('password', [ 'type' => 'password', 'required' => true, + 'id' => 'new-password', 'label' => __d('cake_d_c/users', 'New password')]); ?> + + User->addPasswordMeter() ?> + Form->control('password_confirm', [ 'type' => 'password', 'required' => true, @@ -22,6 +26,6 @@ ?> - Form->button(__d('cake_d_c/users', 'Submit')); ?> + Form->button(__d('cake_d_c/users', 'Submit'), ['id' => 'btn-submit']); ?> Form->end() ?> - \ No newline at end of file + diff --git a/templates/Users/login.php b/templates/Users/login.php index 99aaf4edd..2df2dab9d 100644 --- a/templates/Users/login.php +++ b/templates/Users/login.php @@ -45,6 +45,6 @@ ?> User->socialLoginList()); ?> - Form->button(__d('cake_d_c/users', 'Login')); ?> + User->button(__d('cake_d_c/users', 'Login')); ?> Form->end() ?> diff --git a/templates/Users/profile.php b/templates/Users/profile.php index aa4759fb7..30aa97094 100644 --- a/templates/Users/profile.php +++ b/templates/Users/profile.php @@ -32,7 +32,7 @@

username) ?>

email) ?>

- User->socialConnectLinkList($user->social_accounts) ?> + User->socialConnectLinkList($user->social_accounts ?? []) ?> social_accounts)): ?> diff --git a/templates/Users/register.php b/templates/Users/register.php index e82673b67..4f879e7d9 100644 --- a/templates/Users/register.php +++ b/templates/Users/register.php @@ -19,7 +19,10 @@ Form->control('username', ['label' => __d('cake_d_c/users', 'Username')]); echo $this->Form->control('email', ['label' => __d('cake_d_c/users', 'Email')]); - echo $this->Form->control('password', ['label' => __d('cake_d_c/users', 'Password')]); + echo $this->Form->control('password', ['label' => __d('cake_d_c/users', 'Password'), 'id' => 'new-password']); + if (Configure::read('Users.passwordMeter.enabled')) { + echo $this->User->addPasswordMeter(); + } echo $this->Form->control('password_confirm', [ 'required' => true, 'type' => 'password', @@ -35,6 +38,6 @@ } ?> - Form->button(__d('cake_d_c/users', 'Submit')) ?> + User->button(__d('cake_d_c/users', 'Submit'), ['id' => 'btn-submit']) ?> Form->end() ?> diff --git a/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php index f7b082f13..6ddf61e93 100644 --- a/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php @@ -80,7 +80,7 @@ public function testRequestResetPasswordPostValidEmail() $this->assertResponseContains('Please enter the new password'); $this->assertResponseContains('assertResponseContains('assertResponseContains(''); + $this->assertResponseContains(''); $this->post('/users/change-password', [ 'password' => '9080706050', diff --git a/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php index afa4a15bb..5e27ef5ea 100644 --- a/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php @@ -43,13 +43,13 @@ public function testRegister() $this->assertResponseContains('Add User'); $this->assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); } /** @@ -78,13 +78,13 @@ public function testRegisterPostWithErrors() $this->assertResponseContains('Add User'); $this->assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); } /** diff --git a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php index 6965f9c6a..9a35d74b3 100644 --- a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php @@ -83,7 +83,7 @@ public function testCrud() $this->assertResponseContains('
'); $this->assertResponseContains('assertResponseContains('assertResponseContains(''); + $this->assertResponseContains(''); $this->enableSecurityToken(); $this->post('/users/change-password/00000000-0000-0000-0000-000000000005', [ diff --git a/tests/TestCase/Controller/Traits/Webauthn2FaTraitTest.php b/tests/TestCase/Controller/Traits/Webauthn2FaTraitTest.php index 6dfa19bfd..2550c1194 100644 --- a/tests/TestCase/Controller/Traits/Webauthn2FaTraitTest.php +++ b/tests/TestCase/Controller/Traits/Webauthn2FaTraitTest.php @@ -108,11 +108,10 @@ public function testWebauthn2faIsRegister() $this->Trait ->expects($this->exactly(2)) ->method('set') - ->willReturnCallback(fn ($name, $value) => - match ([$name, $value]) { - ['isRegister', true] => null, - ['username', 'user-2'] => null - }); + ->willReturnCallback(fn ($name, $value) => match ([$name, $value]) { + ['isRegister', true] => null, + ['username', 'user-2'] => null + }); $this->Trait->webauthn2fa(); $this->assertSame( $user, @@ -146,11 +145,10 @@ public function testWebauthn2faDontRequireRegister() $this->Trait ->expects($this->exactly(2)) ->method('set') - ->willReturnCallback(fn ($name, $value) => - match ([$name, $value]) { - ['isRegister', false] => null, - ['username', 'user-1'] => null - }); + ->willReturnCallback(fn ($name, $value) => match ([$name, $value]) { + ['isRegister', false] => null, + ['username', 'user-1'] => null + }); $this->Trait->webauthn2fa(); $this->assertSame( $user, diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index a277ec50a..fb639330b 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -51,6 +51,16 @@ class UserHelperTest extends TestCase */ private $AuthLink; + /** + * @var (\Cake\View\View&\PHPUnit\Framework\MockObject\MockObject)|\PHPUnit\Framework\MockObject\MockObject + */ + private $View; + + /** + * @var ServerRequest + */ + private $request; + /** * setUp method * @@ -237,6 +247,50 @@ public function testAddReCaptcha() $this->assertEquals('
', $result); } + /** + * Test add ReCaptcha V3 + * + * @return void + */ + public function testAddReCaptchaV3() + { + $this->View->expects($this->exactly(2)) + ->method('append') + ->willReturnMap([ + ['https://www.google.com/recaptcha/api.js', null], + ['CakeDC/Users.reCaptchaV3', null], + ]); + Configure::write('Users.reCaptcha.key', 'testKey'); + Configure::write('Users.reCaptcha.version', 3); + Configure::write('Users.reCaptcha.theme', 'light'); + Configure::write('Users.reCaptcha.size', 'normal'); + Configure::write('Users.reCaptcha.tabindex', '3'); + $this->User->Form->create(); + $this->User->addReCaptcha(); + } + + public function testButton() + { + $title = 'test'; + $options = ['test' => 'test']; + $this->assertEquals($this->User->Form->button($title, $options), $this->User->button($title, $options)); + } + + public function testButtonReCaptchaV3() + { + Configure::write('Users.reCaptcha.key', 'testKey'); + Configure::write('Users.reCaptcha.version', 3); + $title = 'test'; + $options = ['test' => 'test']; + $reCaptchaOptions = [ + 'class' => 'g-recaptcha', + 'data-sitekey' => 'testKey', + 'data-callback' => 'onSubmit', + 'data-action' => 'submit', + ]; + $this->assertEquals($this->User->Form->button($title, array_merge($options, $reCaptchaOptions)), $this->User->button($title, $options)); + } + /** * Test add ReCaptcha field * diff --git a/webroot/js/pswmeter.js b/webroot/js/pswmeter.js new file mode 100644 index 000000000..4bbe334e0 --- /dev/null +++ b/webroot/js/pswmeter.js @@ -0,0 +1,151 @@ +/** + * PSWMeter + * @author pascualmj + * @see https://github.com/pascualmj/pswmeter + */ + +/** + * + * @param opts + * @returns {{getScore: (function(): number), containerElement: HTMLElement}} + */ +function passwordStrengthMeter(opts) { + + // Add styles inside body + const customStyles = document.createElement('style') + document.body.prepend(customStyles) + customStyles.innerHTML = ` + ${opts.containerElement} { + height: ${opts.height || 4}px; + background-color: #eee; + position: relative; + overflow: hidden; + border-radius: ${opts.borderRadius ? opt.borderRadius.toString() : 2}px; + } + ${opts.containerElement} .password-strength-meter-score { + height: inherit; + width: 0%; + transition: .3s ease-in-out; + background: ${opts.colorScore1 || '#ff0000'}; + } + ${opts.containerElement} .password-strength-meter-score.psms-25 {width: 25%; background: ${opts.colorScore1 || '#ff0000'};} + ${opts.containerElement} .password-strength-meter-score.psms-50 {width: 50%; background: ${opts.colorScore2 || '#fff400'};} + ${opts.containerElement} .password-strength-meter-score.psms-75 {width: 75%; background: ${opts.colorScore3 || '#a3ff00'};} + ${opts.containerElement} .password-strength-meter-score.psms-100 {width: 100%; background: ${opts.colorScore4 || '#2cba00'};}` + + // Container Element + const containerElement = document.getElementById(opts.containerElement.slice(1)) + containerElement.classList.add('password-strength-meter') + + // Score Bar + let scoreBar = document.createElement('div') + scoreBar.classList.add('password-strength-meter-score') + + // Append score bar to container element + containerElement.appendChild(scoreBar) + + // Password input + const passwordInput = document.getElementById(opts.passwordInput.slice(1)) + let passwordInputValue = '' + passwordInput.addEventListener('keyup', function() { + passwordInputValue = this.value + checkPassword() + }) + + // Chosen Min Length + let pswMinLength = opts.pswMinLength || 8 + + // Score Message + let scoreMessage = opts.showMessage ? document.getElementById(opts.messageContainer.slice(1)) : null + let messagesList = opts.messagesList === undefined ? ['Empty password', 'Too simple', 'Simple', 'That\'s OK', 'Great password!'] : opts.messagesList + if (scoreMessage) { scoreMessage.textContent = messagesList[0] || 'Empty password'} + + // Check Password Function + function checkPassword() { + + let score = getScore() + updateScore(score) + + } + + // Get Score Function + function getScore() { + + let score = 0 + + let regexLower = new RegExp('(?=.*[a-z])') + let regexUpper = new RegExp('(?=.*[A-Z])') + let regexDigits = new RegExp('(?=.*[0-9])') + let regexSymbols = new RegExp('(?=.*[^a-zA-Z\d\s])') + // For length score print user selection or default value + let regexLength = new RegExp('(?=.{' + pswMinLength + ',})') + + if (passwordInputValue.match(regexLower) && passwordInputValue.match(regexUpper)) { ++score } + if (passwordInputValue.match(regexSymbols)) { ++score } + if (passwordInputValue.match(regexDigits)) { ++score } + if (passwordInputValue.match(regexLength)) { ++score } + if (score === 0 && passwordInputValue.length > 0) { ++score } + + return score + } + + // Show Score Function + function updateScore(score) { + switch(score) { + case 1: + scoreBar.className = 'password-strength-meter-score psms-25' + if (scoreMessage) { scoreMessage.textContent = messagesList[1] || 'Too simple' } + containerElement.dispatchEvent(new Event('onScore1', { bubbles: true })) + break + case 2: + scoreBar.className = 'password-strength-meter-score psms-50' + if (scoreMessage) { scoreMessage.textContent = messagesList[2] || 'Simple' } + containerElement.dispatchEvent(new Event('onScore2', { bubbles: true })) + break + case 3: + scoreBar.className = 'password-strength-meter-score psms-75' + if (scoreMessage) { scoreMessage.textContent = messagesList[3] || 'That\'s OK' } + containerElement.dispatchEvent(new Event('onScore3', { bubbles: true })) + break + case 4: + scoreBar.className = 'password-strength-meter-score psms-100' + if (scoreMessage) { scoreMessage.textContent = messagesList[4] || 'Great password!' } + containerElement.dispatchEvent(new Event('onScore4', { bubbles: true })) + break + default: + scoreBar.className = 'password-strength-meter-score' + if (scoreMessage) { scoreMessage.textContent = messagesList[0] || 'No data' } + containerElement.dispatchEvent(new Event('onScore0', { bubbles: true })) + } + } + + // Return anonymous object with properties + return { + containerElement, + getScore + } + +} +window.addEventListener("load",init); +function init() { + // Run pswmeter with options + const myPassMeter = passwordStrengthMeter({ + containerElement: '#pswmeter', + passwordInput: '#new-password', + showMessage: showMessage, + messageContainer: '#pswmeter-message', + messagesList: messagesList, + pswMinLength: pswMinLength, + }); + for (let i = 0; i <= 4; i++) { + myPassMeter.containerElement.addEventListener('onScore' + i, function() { + document.getElementById("btn-submit").disabled = i < requiredScore; + }) + } + + document.getElementById("new-password").dispatchEvent(new Event("keyup")); + if (myPassMeter.getScore < requiredScore) { + document.getElementById("btn-submit").disabled = true; + } + +} diff --git a/webroot/js/reCaptchaV3.js b/webroot/js/reCaptchaV3.js new file mode 100644 index 000000000..42d4d65e7 --- /dev/null +++ b/webroot/js/reCaptchaV3.js @@ -0,0 +1,3 @@ +function onSubmit(token) { + document.forms[0].submit() +}