From 8085c7570d6eca7979adadc77f71ee1ccaff4b1c Mon Sep 17 00:00:00 2001 From: arcmovex <39480923+arcmovex@users.noreply.github.com> Date: Thu, 13 Dec 2018 04:03:33 +0800 Subject: [PATCH 1/3] fix login remember me with google authentication --- src/Controller/Traits/LoginTrait.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 10a99ff12..0a602c85d 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -288,6 +288,14 @@ public function verify() $user['secret_verified'] = true; } + + // Push the remember me value to post data + // for after login event auth + $hasRememberMe = $this->request->getSession()->read('hasRememberMe'); + if ($hasRememberMe) { + $this->request->data(Configure::read('Users.RememberMe.Cookie.name'), $hasRememberMe); + $this->request->getSession()->delete('hasRememberMe'); + } $this->request->getSession()->delete('temporarySession'); $this->Auth->setUser($user); @@ -339,6 +347,13 @@ protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthen // storing user's session in the temporary one // until the GA verification is checked $this->request->getSession()->write('temporarySession', $user); + + // store the remember me value from login into session temporarily + // to pass the value to verify action + if (Configure::read('Users.RememberMe.active')) { + $this->request->getSession()->write('hasRememberMe', $this->request->getData(Configure::read('Users.RememberMe.Cookie.name'))); + } + $url = Configure::read('GoogleAuthenticator.verifyAction'); $url = array_merge($url, [ '?' => $this->request->getQueryParams() From a43e0c6320d4fbc9240d4dc8af62259f96c0559b Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 20 Jan 2019 14:39:20 +0800 Subject: [PATCH 2/3] fix code style login trait for verify and _afterIdentifyUser --- .gitignore | 1 + .semver | 5 - .travis.yml | 50 - CHANGELOG.md | 159 --- CONTRIBUTING.md | 4 - Docs/Documentation/Configuration.md | 195 ---- Docs/Documentation/Events.md | 60 -- Docs/Documentation/Extending-the-Plugin.md | 219 ----- .../Google-Two-Factor-Authenticator.md | 36 - .../Documentation/GoogleAuthenticator/App.png | Bin 52261 -> 0 bytes .../GoogleAuthenticator/FirstLogin.png | Bin 21106 -> 0 bytes Docs/Documentation/Installation.md | 115 --- Docs/Documentation/Migration/4.x-5.0.md | 56 -- Docs/Documentation/Migration/6.x-7.0.md | 18 - Docs/Documentation/Overview.md | 19 - Docs/Documentation/SocialAuthenticate.md | 97 -- Docs/Documentation/Translations.md | 17 - Docs/Documentation/UserHelper.md | 85 -- Docs/Home.md | 32 - LICENSE.txt | 26 - README.md | 74 -- composer.json | 2 +- config/Migrations/20150513201111_initial.php | 152 --- .../20161031101316_AddSecretToUsers.php | 43 - config/Migrations/schema-dump-default.lock | Bin 7938 -> 0 bytes config/bootstrap.php | 49 - config/permissions.php | 91 -- config/routes.php | 52 - config/users.php | 206 ---- phpunit.xml.dist | 36 - .../DefaultTwoFactorAuthenticationChecker.php | 44 - .../Exception/InvalidProviderException.php | 31 - .../Exception/InvalidSettingsException.php | 31 - .../MissingEventListenerException.php | 30 - .../MissingProviderConfigurationException.php | 31 - src/Auth/Social/Mapper/AbstractMapper.php | 119 --- src/Auth/Social/Mapper/Amazon.php | 43 - src/Auth/Social/Mapper/Facebook.php | 52 - src/Auth/Social/Mapper/Google.php | 43 - src/Auth/Social/Mapper/Instagram.php | 43 - src/Auth/Social/Mapper/LinkedIn.php | 28 - src/Auth/Social/Mapper/Pinterest.php | 24 - src/Auth/Social/Mapper/Tumblr.php | 46 - src/Auth/Social/Mapper/Twitter.php | 59 -- src/Auth/Social/Util/SocialUtils.php | 35 - src/Auth/SocialAuthenticate.php | 488 ---------- .../TwoFactorAuthenticationCheckerFactory.php | 39 - ...woFactorAuthenticationCheckerInterface.php | 30 - src/Controller/AppController.php | 36 - .../GoogleAuthenticatorComponent.php | 84 -- .../Component/RememberMeComponent.php | 159 --- src/Controller/Component/SetupComponent.php | 33 - .../Component/UsersAuthComponent.php | 247 ----- src/Controller/SocialAccountsController.php | 94 -- .../Traits/CustomUsersTableTrait.php | 51 - src/Controller/Traits/LinkSocialTrait.php | 237 ----- src/Controller/Traits/LoginTrait.php | 14 +- .../Traits/PasswordManagementTrait.php | 180 ---- src/Controller/Traits/ProfileTrait.php | 61 -- src/Controller/Traits/ReCaptchaTrait.php | 57 -- src/Controller/Traits/RegisterTrait.php | 155 --- src/Controller/Traits/SimpleCrudTrait.php | 138 --- src/Controller/Traits/SocialTrait.php | 49 - src/Controller/Traits/UserValidationTrait.php | 123 --- src/Controller/UsersController.php | 41 - .../AccountAlreadyActiveException.php | 28 - src/Exception/AccountNotActiveException.php | 30 - src/Exception/BadConfigurationException.php | 28 - src/Exception/MissingEmailException.php | 28 - src/Exception/MissingProviderException.php | 28 - src/Exception/TokenExpiredException.php | 28 - src/Exception/UserAlreadyActiveException.php | 28 - src/Exception/UserNotActiveException.php | 28 - src/Exception/UserNotFoundException.php | 28 - src/Exception/WrongPasswordException.php | 28 - src/Locale/Users.pot | 821 ---------------- src/Locale/ar_OM/Users.mo | Bin 18521 -> 0 bytes src/Locale/ar_OM/Users.po | 819 ---------------- src/Locale/es/Users.mo | Bin 15243 -> 0 bytes src/Locale/es/Users.po | 854 ---------------- src/Locale/fr_FR/Users.mo | Bin 16147 -> 0 bytes src/Locale/fr_FR/Users.po | 837 ---------------- src/Locale/hu_HU/Users.mo | Bin 14725 -> 0 bytes src/Locale/hu_HU/Users.po | 816 ---------------- src/Locale/it_IT/Users.mo | Bin 15385 -> 0 bytes src/Locale/it_IT/Users.po | 783 --------------- src/Locale/pl/Users.mo | Bin 14520 -> 0 bytes src/Locale/pl/Users.po | 811 ---------------- src/Locale/pt_BR/Users.mo | Bin 15088 -> 0 bytes src/Locale/pt_BR/Users.po | 908 ------------------ src/Locale/sv/Users.mo | Bin 14831 -> 0 bytes src/Locale/sv/Users.po | 864 ----------------- src/Locale/tr_TR/Users.mo | Bin 15267 -> 0 bytes src/Locale/tr_TR/Users.po | 819 ---------------- src/Mailer/UsersMailer.php | 81 -- src/Model/Behavior/AuthFinderBehavior.php | 62 -- src/Model/Behavior/BaseTokenBehavior.php | 59 -- src/Model/Behavior/LinkSocialBehavior.php | 141 --- src/Model/Behavior/PasswordBehavior.php | 159 --- src/Model/Behavior/RegisterBehavior.php | 210 ---- src/Model/Behavior/SocialAccountBehavior.php | 152 --- src/Model/Behavior/SocialBehavior.php | 261 ----- src/Model/Entity/SocialAccount.php | 41 - src/Model/Entity/User.php | 163 ---- src/Model/Table/SocialAccountsTable.php | 133 --- src/Model/Table/UsersTable.php | 185 ---- src/Shell/UsersShell.php | 404 -------- src/Template/Email/html/reset_password.ctp | 35 - .../Email/html/social_account_validation.ctp | 40 - src/Template/Email/html/validation.ctp | 35 - src/Template/Email/text/reset_password.ctp | 29 - .../Email/text/social_account_validation.ctp | 31 - src/Template/Email/text/validation.ctp | 29 - src/Template/Layout/Email/html/default.ctp | 20 - src/Template/Layout/Email/text/default.ctp | 13 - src/Template/Users/add.ctp | 36 - src/Template/Users/change_password.ctp | 27 - src/Template/Users/edit.ctp | 77 -- src/Template/Users/index.ctp | 55 -- src/Template/Users/login.ctp | 50 - src/Template/Users/profile.ctp | 78 -- src/Template/Users/register.ctp | 38 - src/Template/Users/request_reset_password.ctp | 10 - .../Users/resend_token_validation.ctp | 22 - src/Template/Users/social_email.ctp | 21 - src/Template/Users/verify.ctp | 20 - src/Template/Users/view.ctp | 90 -- src/Traits/RandomStringTrait.php | 30 - src/View/Helper/AuthLinkHelper.php | 68 -- src/View/Helper/UserHelper.php | 254 ----- tests/App/Controller/AppController.php | 33 - tests/App/Mailer/OverrideMailer.php | 34 - .../text/custom_template_in_app_namespace.ctp | 1 - .../Template/Layout/Email/html/default.ctp | 2 - .../Template/Layout/Email/text/default.ctp | 2 - tests/Fixture/PostsFixture.php | 60 -- tests/Fixture/PostsUsersFixture.php | 60 -- tests/Fixture/SocialAccountsFixture.php | 141 --- tests/Fixture/UsersFixture.php | 267 ----- ...aultTwoFactorAuthenticationCheckerTest.php | 67 -- .../InvalidProviderExceptionTest.php | 46 - .../InvalidSettingsExceptionTest.php | 46 - .../MissingEventListenerExceptionTest.php | 45 - ...singProviderConfigurationExceptionTest.php | 46 - .../Auth/Social/Mapper/FacebookTest.php | 91 -- .../Auth/Social/Mapper/GoogleTest.php | 73 -- .../Auth/Social/Mapper/InstagramTest.php | 72 -- .../Auth/Social/Mapper/LinkedInTest.php | 75 -- .../Auth/Social/Mapper/TwitterTest.php | 71 -- .../TestCase/Auth/SocialAuthenticateTest.php | 644 ------------- ...FactorAuthenticationCheckerFactoryTest.php | 44 - .../GoogleAuthenticatorComponentTest.php | 136 --- .../Component/RememberMeComponentTest.php | 194 ---- .../Component/UsersAuthComponentTest.php | 515 ---------- .../SocialAccountsControllerTest.php | 204 ---- .../Controller/Traits/BaseTraitTest.php | 220 ----- .../Traits/CustomUsersTableTraitTest.php | 41 - .../Controller/Traits/LinkSocialTraitTest.php | 825 ---------------- .../Controller/Traits/LoginTraitTest.php | 813 ---------------- .../Traits/PasswordManagementTraitTest.php | 470 --------- .../Controller/Traits/ProfileTraitTest.php | 113 --- .../Controller/Traits/RecaptchaTraitTest.php | 123 --- .../Controller/Traits/RegisterTraitTest.php | 399 -------- .../Controller/Traits/SimpleCrudTraitTest.php | 306 ------ .../Controller/Traits/SocialTraitTest.php | 180 ---- .../Traits/UserValidationTraitTest.php | 243 ----- .../AccountAlreadyActiveExceptionTest.php | 43 - .../AccountNotActiveExceptionTest.php | 45 - .../BadConfigurationExceptionTest.php | 43 - .../Exception/MissingEmailExceptionTest.php | 43 - .../MissingProviderExceptionTest.php | 43 - .../Exception/TokenExpiredExceptionTest.php | 43 - .../UserAlreadyActiveExceptionTest.php | 43 - .../Exception/UserNotActiveExceptionTest.php | 43 - .../Exception/UserNotFoundExceptionTest.php | 43 - .../Exception/WrongPasswordExceptionTest.php | 43 - tests/TestCase/Mailer/UsersMailerTest.php | 172 ---- .../Model/Behavior/AuthFinderBehaviorTest.php | 104 -- .../Model/Behavior/LinkSocialBehaviorTest.php | 363 ------- .../Model/Behavior/PasswordBehaviorTest.php | 237 ----- .../Model/Behavior/RegisterBehaviorTest.php | 320 ------ .../Behavior/SocialAccountBehaviorTest.php | 141 --- .../Model/Behavior/SocialBehaviorTest.php | 388 -------- tests/TestCase/Model/Entity/UserTest.php | 206 ---- .../Model/Table/SocialAccountsTableTest.php | 74 -- tests/TestCase/Model/Table/UsersTableTest.php | 312 ------ tests/TestCase/Shell/UsersShellTest.php | 418 -------- .../TestCase/Traits/RandomStringTraitTest.php | 43 - .../View/Helper/AuthLinkHelperTest.php | 156 --- tests/TestCase/View/Helper/UserHelperTest.php | 380 -------- tests/bootstrap.php | 130 --- tests/config/routes.php | 35 - webroot/empty | 0 webroot/img/avatar_placeholder.png | Bin 4015 -> 0 bytes 194 files changed, 7 insertions(+), 27253 deletions(-) delete mode 100644 .semver delete mode 100644 .travis.yml delete mode 100644 CHANGELOG.md delete mode 100644 CONTRIBUTING.md delete mode 100644 Docs/Documentation/Configuration.md delete mode 100644 Docs/Documentation/Events.md delete mode 100644 Docs/Documentation/Extending-the-Plugin.md delete mode 100644 Docs/Documentation/Google-Two-Factor-Authenticator.md delete mode 100644 Docs/Documentation/GoogleAuthenticator/App.png delete mode 100644 Docs/Documentation/GoogleAuthenticator/FirstLogin.png delete mode 100644 Docs/Documentation/Installation.md delete mode 100644 Docs/Documentation/Migration/4.x-5.0.md delete mode 100644 Docs/Documentation/Migration/6.x-7.0.md delete mode 100644 Docs/Documentation/Overview.md delete mode 100644 Docs/Documentation/SocialAuthenticate.md delete mode 100644 Docs/Documentation/Translations.md delete mode 100644 Docs/Documentation/UserHelper.md delete mode 100644 Docs/Home.md delete mode 100644 LICENSE.txt delete mode 100644 README.md delete mode 100644 config/Migrations/20150513201111_initial.php delete mode 100644 config/Migrations/20161031101316_AddSecretToUsers.php delete mode 100644 config/Migrations/schema-dump-default.lock delete mode 100644 config/bootstrap.php delete mode 100644 config/permissions.php delete mode 100644 config/routes.php delete mode 100644 config/users.php delete mode 100644 phpunit.xml.dist delete mode 100644 src/Auth/DefaultTwoFactorAuthenticationChecker.php delete mode 100644 src/Auth/Exception/InvalidProviderException.php delete mode 100644 src/Auth/Exception/InvalidSettingsException.php delete mode 100644 src/Auth/Exception/MissingEventListenerException.php delete mode 100644 src/Auth/Exception/MissingProviderConfigurationException.php delete mode 100644 src/Auth/Social/Mapper/AbstractMapper.php delete mode 100644 src/Auth/Social/Mapper/Amazon.php delete mode 100644 src/Auth/Social/Mapper/Facebook.php delete mode 100644 src/Auth/Social/Mapper/Google.php delete mode 100644 src/Auth/Social/Mapper/Instagram.php delete mode 100644 src/Auth/Social/Mapper/LinkedIn.php delete mode 100644 src/Auth/Social/Mapper/Pinterest.php delete mode 100644 src/Auth/Social/Mapper/Tumblr.php delete mode 100644 src/Auth/Social/Mapper/Twitter.php delete mode 100644 src/Auth/Social/Util/SocialUtils.php delete mode 100755 src/Auth/SocialAuthenticate.php delete mode 100644 src/Auth/TwoFactorAuthenticationCheckerFactory.php delete mode 100644 src/Auth/TwoFactorAuthenticationCheckerInterface.php delete mode 100644 src/Controller/AppController.php delete mode 100644 src/Controller/Component/GoogleAuthenticatorComponent.php delete mode 100644 src/Controller/Component/RememberMeComponent.php delete mode 100644 src/Controller/Component/SetupComponent.php delete mode 100644 src/Controller/Component/UsersAuthComponent.php delete mode 100644 src/Controller/SocialAccountsController.php delete mode 100644 src/Controller/Traits/CustomUsersTableTrait.php delete mode 100644 src/Controller/Traits/LinkSocialTrait.php delete mode 100644 src/Controller/Traits/PasswordManagementTrait.php delete mode 100644 src/Controller/Traits/ProfileTrait.php delete mode 100644 src/Controller/Traits/ReCaptchaTrait.php delete mode 100644 src/Controller/Traits/RegisterTrait.php delete mode 100644 src/Controller/Traits/SimpleCrudTrait.php delete mode 100644 src/Controller/Traits/SocialTrait.php delete mode 100644 src/Controller/Traits/UserValidationTrait.php delete mode 100644 src/Controller/UsersController.php delete mode 100644 src/Exception/AccountAlreadyActiveException.php delete mode 100644 src/Exception/AccountNotActiveException.php delete mode 100644 src/Exception/BadConfigurationException.php delete mode 100644 src/Exception/MissingEmailException.php delete mode 100644 src/Exception/MissingProviderException.php delete mode 100644 src/Exception/TokenExpiredException.php delete mode 100644 src/Exception/UserAlreadyActiveException.php delete mode 100644 src/Exception/UserNotActiveException.php delete mode 100644 src/Exception/UserNotFoundException.php delete mode 100644 src/Exception/WrongPasswordException.php delete mode 100644 src/Locale/Users.pot delete mode 100644 src/Locale/ar_OM/Users.mo delete mode 100644 src/Locale/ar_OM/Users.po delete mode 100644 src/Locale/es/Users.mo delete mode 100644 src/Locale/es/Users.po delete mode 100644 src/Locale/fr_FR/Users.mo delete mode 100644 src/Locale/fr_FR/Users.po delete mode 100644 src/Locale/hu_HU/Users.mo delete mode 100644 src/Locale/hu_HU/Users.po delete mode 100644 src/Locale/it_IT/Users.mo delete mode 100644 src/Locale/it_IT/Users.po delete mode 100644 src/Locale/pl/Users.mo delete mode 100644 src/Locale/pl/Users.po delete mode 100644 src/Locale/pt_BR/Users.mo delete mode 100644 src/Locale/pt_BR/Users.po delete mode 100644 src/Locale/sv/Users.mo delete mode 100644 src/Locale/sv/Users.po delete mode 100644 src/Locale/tr_TR/Users.mo delete mode 100644 src/Locale/tr_TR/Users.po delete mode 100644 src/Mailer/UsersMailer.php delete mode 100644 src/Model/Behavior/AuthFinderBehavior.php delete mode 100644 src/Model/Behavior/BaseTokenBehavior.php delete mode 100644 src/Model/Behavior/LinkSocialBehavior.php delete mode 100644 src/Model/Behavior/PasswordBehavior.php delete mode 100644 src/Model/Behavior/RegisterBehavior.php delete mode 100644 src/Model/Behavior/SocialAccountBehavior.php delete mode 100644 src/Model/Behavior/SocialBehavior.php delete mode 100644 src/Model/Entity/SocialAccount.php delete mode 100644 src/Model/Entity/User.php delete mode 100644 src/Model/Table/SocialAccountsTable.php delete mode 100644 src/Model/Table/UsersTable.php delete mode 100644 src/Shell/UsersShell.php delete mode 100644 src/Template/Email/html/reset_password.ctp delete mode 100644 src/Template/Email/html/social_account_validation.ctp delete mode 100644 src/Template/Email/html/validation.ctp delete mode 100644 src/Template/Email/text/reset_password.ctp delete mode 100644 src/Template/Email/text/social_account_validation.ctp delete mode 100644 src/Template/Email/text/validation.ctp delete mode 100644 src/Template/Layout/Email/html/default.ctp delete mode 100644 src/Template/Layout/Email/text/default.ctp delete mode 100644 src/Template/Users/add.ctp delete mode 100644 src/Template/Users/change_password.ctp delete mode 100644 src/Template/Users/edit.ctp delete mode 100644 src/Template/Users/index.ctp delete mode 100644 src/Template/Users/login.ctp delete mode 100644 src/Template/Users/profile.ctp delete mode 100644 src/Template/Users/register.ctp delete mode 100644 src/Template/Users/request_reset_password.ctp delete mode 100644 src/Template/Users/resend_token_validation.ctp delete mode 100644 src/Template/Users/social_email.ctp delete mode 100644 src/Template/Users/verify.ctp delete mode 100644 src/Template/Users/view.ctp delete mode 100644 src/Traits/RandomStringTrait.php delete mode 100644 src/View/Helper/AuthLinkHelper.php delete mode 100644 src/View/Helper/UserHelper.php delete mode 100644 tests/App/Controller/AppController.php delete mode 100644 tests/App/Mailer/OverrideMailer.php delete mode 100644 tests/App/Template/Email/text/custom_template_in_app_namespace.ctp delete mode 100644 tests/App/Template/Layout/Email/html/default.ctp delete mode 100644 tests/App/Template/Layout/Email/text/default.ctp delete mode 100644 tests/Fixture/PostsFixture.php delete mode 100644 tests/Fixture/PostsUsersFixture.php delete mode 100644 tests/Fixture/SocialAccountsFixture.php delete mode 100644 tests/Fixture/UsersFixture.php delete mode 100644 tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php delete mode 100644 tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php delete mode 100644 tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php delete mode 100644 tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php delete mode 100644 tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php delete mode 100644 tests/TestCase/Auth/Social/Mapper/FacebookTest.php delete mode 100644 tests/TestCase/Auth/Social/Mapper/GoogleTest.php delete mode 100644 tests/TestCase/Auth/Social/Mapper/InstagramTest.php delete mode 100644 tests/TestCase/Auth/Social/Mapper/LinkedInTest.php delete mode 100644 tests/TestCase/Auth/Social/Mapper/TwitterTest.php delete mode 100644 tests/TestCase/Auth/SocialAuthenticateTest.php delete mode 100644 tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php delete mode 100644 tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php delete mode 100644 tests/TestCase/Controller/Component/RememberMeComponentTest.php delete mode 100644 tests/TestCase/Controller/Component/UsersAuthComponentTest.php delete mode 100644 tests/TestCase/Controller/SocialAccountsControllerTest.php delete mode 100644 tests/TestCase/Controller/Traits/BaseTraitTest.php delete mode 100644 tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php delete mode 100644 tests/TestCase/Controller/Traits/LinkSocialTraitTest.php delete mode 100644 tests/TestCase/Controller/Traits/LoginTraitTest.php delete mode 100644 tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php delete mode 100644 tests/TestCase/Controller/Traits/ProfileTraitTest.php delete mode 100644 tests/TestCase/Controller/Traits/RecaptchaTraitTest.php delete mode 100644 tests/TestCase/Controller/Traits/RegisterTraitTest.php delete mode 100644 tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php delete mode 100644 tests/TestCase/Controller/Traits/SocialTraitTest.php delete mode 100644 tests/TestCase/Controller/Traits/UserValidationTraitTest.php delete mode 100644 tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php delete mode 100644 tests/TestCase/Exception/AccountNotActiveExceptionTest.php delete mode 100644 tests/TestCase/Exception/BadConfigurationExceptionTest.php delete mode 100644 tests/TestCase/Exception/MissingEmailExceptionTest.php delete mode 100644 tests/TestCase/Exception/MissingProviderExceptionTest.php delete mode 100644 tests/TestCase/Exception/TokenExpiredExceptionTest.php delete mode 100644 tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php delete mode 100644 tests/TestCase/Exception/UserNotActiveExceptionTest.php delete mode 100644 tests/TestCase/Exception/UserNotFoundExceptionTest.php delete mode 100644 tests/TestCase/Exception/WrongPasswordExceptionTest.php delete mode 100644 tests/TestCase/Mailer/UsersMailerTest.php delete mode 100644 tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php delete mode 100644 tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php delete mode 100644 tests/TestCase/Model/Behavior/PasswordBehaviorTest.php delete mode 100644 tests/TestCase/Model/Behavior/RegisterBehaviorTest.php delete mode 100644 tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php delete mode 100644 tests/TestCase/Model/Behavior/SocialBehaviorTest.php delete mode 100644 tests/TestCase/Model/Entity/UserTest.php delete mode 100644 tests/TestCase/Model/Table/SocialAccountsTableTest.php delete mode 100644 tests/TestCase/Model/Table/UsersTableTest.php delete mode 100644 tests/TestCase/Shell/UsersShellTest.php delete mode 100644 tests/TestCase/Traits/RandomStringTraitTest.php delete mode 100644 tests/TestCase/View/Helper/AuthLinkHelperTest.php delete mode 100644 tests/TestCase/View/Helper/UserHelperTest.php delete mode 100644 tests/bootstrap.php delete mode 100644 tests/config/routes.php delete mode 100644 webroot/empty delete mode 100644 webroot/img/avatar_placeholder.png diff --git a/.gitignore b/.gitignore index c89d5a392..3ca489870 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ composer.lock .php_cs* /coverage +/nbproject/private/ \ No newline at end of file diff --git a/.semver b/.semver deleted file mode 100644 index af406a57b..000000000 --- a/.semver +++ /dev/null @@ -1,5 +0,0 @@ ---- -:major: 8 -:minor: 0 -:patch: 2 -:special: '' diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e71ec741f..000000000 --- a/.travis.yml +++ /dev/null @@ -1,50 +0,0 @@ -language: php - -php: - - 5.6 - - 7.0 - - 7.1 - - 7.2 - -sudo: false - -env: - matrix: - - DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' - - DB=pgsql db_dsn='postgres://postgres@127.0.0.1/cakephp_test' - - DB=sqlite db_dsn='sqlite:///:memory:' - - global: - - DEFAULT=1 - -matrix: - fast_finish: true - - include: - - php: 7.1 - env: PHPCS=1 DEFAULT=0 - - - php: 7.1 - env: CODECOVERAGE=1 DEFAULT=0 DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' - -before_script: - - composer self-update - - composer install --prefer-dist --no-interaction - - - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'CREATE DATABASE cakephp_test; GRANT ALL PRIVILEGES ON cakephp_test.* TO travis@localhost;'; fi" - - sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi" - - - sh -c "if [ '$PHPCS' = '1' ]; then composer require 'cakephp/cakephp-codesniffer:@stable'; fi" - - sh -c "if [ '$COVERALLS' = '1' ]; then composer require --dev 'satooshi/php-coveralls:^2.0'; fi" - - - sh -c "if [ '$COVERALLS' = '1' ]; then mkdir -p build/logs; fi" - -script: - - sh -c "if [ '$DEFAULT' = '1' ]; then ./vendor/bin/phpunit --stderr; fi" - - sh -c "if [ '$PHPCS' = '1' ]; then ./vendor/bin/phpcs -p -n --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests; fi" - - sh -c "if [ '$CODECOVERAGE' = '1' ]; then phpunit --coverage-clover=clover.xml || true; fi" - - sh -c "if [ '$CODECOVERAGE' = '1' ]; then wget -O codecov.sh https://codecov.io/bash; fi" - - sh -c "if [ '$CODECOVERAGE' = '1' ]; then bash codecov.sh; fi" - -notifications: - email: false diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 7ba444c97..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,159 +0,0 @@ -Changelog -========= - -Releases for CakePHP 3 -------------- - -* 8.0.2 - * Add default role for users registered via social login - -* 8.0.1 - * Fixed 2fa link preserve querystring - -* 8.0.0 - * Added new events `Users.Component.UsersAuth.onExpiredToken` and `Users.Component.UsersAuth.afterResendTokenValidation` - * Added 2 factor authentication checkers to allow customization - * Added Mapper classes to social auth services as a way to generalize url/avatar retrieval - * Fix issues with recent changes in Facebook API - * Added new translations - * Improved customization options for recaptcha integration - -* 7.0.2 - * Fixed an issue with 2FA only working on the second try - -* 7.0.1 - * Fixed a security issue in 2 factor authentication, reported by @ndm2 - * Updated to cakedc/auth ^3.0 - * Documentation fixes - -* 7.0.0 - * Removed deprecations for CakePHP 3.6 - * Added a new `UsersAuthComponent::EVENT_AFTER_CHANGE_PASSWORD` - * Updated docs - -* 6.0.0 - * Removed deprecations and orWhere usage - * Amazon login implemented - * Fixed issues with login via twitter - * Updated Facebook Graph version to 2.8 - * Fixed flash error messages on logic - * Added link social account feature for twitter - * Switched to codecov - -* 5.2.0 - * Compatible with 3.5, deprecations will be removed in next major version of the plugin - * Username is now custom in SocialBehavior - * Better handling of the RememberMe checkbox - * Updated CakeDC/Auth to use ^2.0 - * Use of UsersMailer class, and allow override of the emails sent by the plugin - * Better token generation via randomBytes - * Improved documentation - * Fixed bugs reported - -* 5.1.0 - * New resend validation method in RegisterBehavior - * Allow upgrade to CakePHP 3.5.x - * New feature connect social account - * New polish translations - * Fixed bugs reported - -* 5.0.3 - * Implemented event dispatching on social login - * Fixed bugs reported - * Don't check for allowed actions in other controllers - -* 5.0.2 - * Fixed bug parsing rule urls when application installed in a subdirectory - -* 5.0.1 - * Bugfix release - * Minor BR language improvements - -* 5.0.0 - * Some Auth objects refactored into https://github.com/CakeDC/auth - * Upgrade to CakePHP 3.4 - -* 4.2.1 - * Improvements in unit tests - -* 4.2.0 - * New configuration param `Users.Registration.defaultRole` to set the default role on user registration or addUser Shell action - -* 4.1.3 - * Configurable rememberMe checkbox status - * Update brazilian portuguese translations - * Add active finder to SocialAccountsTable - * Improvements in UsersShell for superuser add options - * Update to robthree/twofactorauth 1.6 - * UserHelper improvements - -* 4.1.2 - * Fix RememberMe redirect - * Fix AuthLink rendering inside Cells - -* 4.1.1 - * Add missing password field in add user - -* 4.1.0 - * Add reset action for Google Authenticator - -* 4.0.0 - * Add Google Authenticator - * Add improvements to SimpleRbac, like star to invert rules and `user.` prefix to match values from the user array - * Add `allowed` to manage the AuthLinkHelper when action is allowed - * Add option to configure the api table and finder in ApiKeyAuthenticate - -* 3.2.5 - * Fixed RegisterBehavior api, make getRegisterValidators public. - -* 3.2.3 - * Added compatibility with CakePHP 3.3+ - * Fixed several bugs, including regression issue with Facebook login & improvements - -* 3.2.2 - * Fix bug with socialLogin links not being displayed for unauthenticated users - -* 3.2.1 - * New Translations (see https://github.com/CakeDC/users/blob/master/Docs/Documentation/Translations.md) - * Stateless API Authenticate support - * Prefix and extension support in permission rules (RBAC) - * Improved registration and reset password user already logged in logic - * Several bugfixes - * AuthLinkHelper added to render links if user is allowed only - -* 3.1.5 - * SocialAuthenticate improvements - * Authorize Rules. Owner rule - * Docs improvements - -* 3.1.4 - * SocialAuthenticate refactored to drop Opauth in favor of Muffin/OAuth2 and league/oauth2 - -* 3.1.3 - * UserHelper improvements - -* 3.1.2 - * Fixes in RBAC permission matchers - -* 3.1.0 Migration to CakePHP 3.0 - * Unit test coverage improvements - * Refactor UsersTable to Behavior - * Add google authentication - * Add reCaptcha - * Link social accounts in profile - -Releases for CakePHP 2 -------------- - -* 2.1.3 - * Fixed unit tests for compatibility with CakePHP 2.7 - -* 2.1.2 - * Minor improvements - * New translations (german and portuguese) - -* 2.1.1 - * Forgot password - -* 2.1.0 - * Bugfixes and improvements diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 653b64f7c..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,4 +0,0 @@ -Contributing -============ - -This repository follows the [CakeDC Plugin Standard](https://www.cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](https://www.cakedc.com/contribution-guidelines) for detailed instructions. diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md deleted file mode 100644 index f52015acb..000000000 --- a/Docs/Documentation/Configuration.md +++ /dev/null @@ -1,195 +0,0 @@ -Configuration -============= - -Overriding the default configuration -------------------------- - -For easier configuration, you can specify an array of config files to override the default plugin keys this way: - -config/bootstrap.php -``` -// The following configuration setting must be set before loading the Users plugin -Configure::write('Users.config', ['users']); -Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); -Configure::write('Users.Social.login', true); //to enable social login -``` - -Configuration for social login ---------------------- - -Create the facebook, twitter, etc applications you want to use and setup the configuration like this: -In this example, we are using 2 providers: facebook and twitter. Note you'll need to add the providers to -your composer.json file. - -``` -$ composer require league/oauth2-facebook:@stable -$ composer require league/oauth1-client:@stable -``` - -NOTE: twitter uses league/oauth1-client package - -config/bootstrap.php -``` -Configure::write('OAuth.providers.facebook.options.clientId', 'YOUR APP ID'); -Configure::write('OAuth.providers.facebook.options.clientSecret', 'YOUR APP SECRET'); - -Configure::write('OAuth.providers.twitter.options.clientId', 'YOUR APP ID'); -Configure::write('OAuth.providers.twitter.options.clientSecret', 'YOUR APP SECRET'); -``` - -Or use the config override option when loading the plugin (see above) - -Additionally you will see you can configure two more keys for each provider: - -* linkSocialUri (default: /link-social/**provider**), -* callbackLinkSocialUri(default: /callback-link-social/**provider**) - -Those keys are needed to link an existing user account to a third-party account. **Remember to add the callback to your thrid-party app** - -Configuration for reCaptcha ---------------------- -``` -Configure::write('Users.reCaptcha.key', 'YOUR RECAPTCHA KEY'); -Configure::write('Users.reCaptcha.secret', 'YOUR RECAPTCHA SECRET'); -Configure::write('Users.reCaptcha.registration', true); //enable on registration -Configure::write('Users.reCaptcha.login', true); //enable on login -``` - - -Configuration options ---------------------- - -The plugin is configured via the Configure class. Check the `vendor/cakedc/users/config/users.php` -for a complete list of all the configuration keys. - -Loading the UsersAuthComponent and using the right configuration values will setup the Users plugin, -the AuthComponent and the OAuth component for your application. - -If you prefer to setup AuthComponent by yourself, you'll need to load AuthComponent before UsersAuthComponent -and set -``` -Configure::write('Users.auth', false); -``` - -Interesting UsersAuthComponent options and defaults - -NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/users/config/users.php` for the complete list - -``` - 'Users' => [ - // Table used to manage users - 'table' => 'CakeDC/Users.Users', - // Controller used to manage users plugin features & actions - 'controller' => 'CakeDC/Users.Users', - // configure Auth component - 'auth' => true, - 'Email' => [ - // determines if the user should include email - 'required' => true, - // determines if registration workflow includes email validation - 'validate' => true, - ], - 'Registration' => [ - // determines if the register is enabled - 'active' => true, - // determines if the reCaptcha is enabled for registration - 'reCaptcha' => true, - //ensure user is active (confirmed email) to reset his password - 'ensureActive' => false, - // default role name used in registration - 'defaultRole' => 'user', - ], - 'Tos' => [ - // determines if the user should include tos accepted - 'required' => true, - ], - 'Social' => [ - // enable social login - 'login' => false, - ], - // Avatar placeholder - 'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'], - 'RememberMe' => [ - // configure Remember Me component - 'active' => true, - ], - ], -// default configuration used to auto-load the Auth Component, override to change the way Auth works - 'Auth' => [ - 'authenticate' => [ - 'all' => [ - 'finder' => 'active', - ], - 'CakeDC/Auth.RememberMe', - 'Form', - ], - 'authorize' => [ - 'CakeDC/Auth.Superuser', - 'CakeDC/Auth.SimpleRbac', - ], - ], -]; - -``` - -Default Authenticate and Authorize Objects used ------------------------- - -Using the UsersAuthComponent default initialization, the component will load the following objects into AuthComponent: -* Authenticate - * 'Form' - * 'CakeDC/Users.Social' check [SocialAuthenticate](SocialAuthenticate.md) for configuration options - * 'CakeDC/Auth.RememberMe' check [RememberMeAuthenticate](https://github.com/CakeDC/auth/blob/master/src/RememberMeAuthenticate.php) for configuration options - * 'CakeDC/Auth.ApiKey' check [ApiKeyAuthenticate](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/ApiKeyAuthenticate.md) for configuration options -* Authorize - * 'CakeDC/Auth.Superuser' check [SuperuserAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SuperuserAuthorize.md) for configuration options - * 'CakeDC/Auth.SimpleRbac' check [SimpleRbacAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SimpleRbacAuthorize.md) for configuration options - -## Using the user's email to login - -You need to configure 2 things: -* Change the Auth.authenticate.Form.fields configuration to let AuthComponent use the email instead of the username for user identify. Add this line to your bootstrap.php file, after CakeDC/Users Plugin is loaded - -```php -Configure::write('Auth.authenticate.Form.fields.username', 'email'); -``` - -* Override the login.ctp template to change the Form->control to "email". Add (or copy from the https://github.com/CakeDC/users/blob/master/src/Template/Users/login.ctp) the file login.ctp to path /src/Template/Plugin/CakeDC/Users/Users/login.ctp and ensure it has the following content - -```php - // ... inside the Form - Form->control('email', ['required' => true]) ?> - Form->control('password', ['required' => true]) ?> - // ... rest of your login.ctp code -``` - - - - -Email Templates ---------------- - -To modify the templates as needed copy them to your application - -``` -cp -r vendor/cakedc/users/src/Template/Email/* src/Template/Plugin/CakeDC/Users/Email/ -``` - -Then customize the email templates as you need under the src/Template/Plugin/CakeDC/Users/Email/ directory - -Plugin Templates ---------------- - -Similar to Email Templates customization, follow the CakePHP conventions to put your new templates under -src/Template/Plugin/CakeDC/Users/[Controller]/[view].ctp - -Check http://book.cakephp.org/3.0/en/plugins.html#overriding-plugin-templates-from-inside-your-application - -Flash Messages ---------------- - -To modify the flash messages, use the standard PO file provided by the plugin and customize the messages -Check http://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html#setting-up-translations -for more details about how the PO files should be managed in your application. - -We've included an updated POT file with all the `Users` domain keys for your customization. diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md deleted file mode 100644 index 1308d0705..000000000 --- a/Docs/Documentation/Events.md +++ /dev/null @@ -1,60 +0,0 @@ -Events -====== - -The events in this plugin follow these conventions `...`: - -* `Users.Component.UsersAuth.isAuthorized` -* `Users.Component.UsersAuth.beforeLogin` -* `Users.Component.UsersAuth.afterLogin` -* `Users.Component.UsersAuth.failedSocialLogin` -* `Users.Component.UsersAuth.afterCookieLogin` -* `Users.Component.UsersAuth.beforeRegister` -* `Users.Component.UsersAuth.afterRegister` -* `Users.Component.UsersAuth.beforeLogout` -* `Users.Component.UsersAuth.afterLogout` -* `Users.Component.UsersAuth.beforeSocialLoginUserCreate` -* `Users.Component.UsersAuth.afterResetPassword` -* `Users.Component.UsersAuth.onExpiredToken` -* `Users.Component.UsersAuth.afterResendTokenValidation` - -The events allow you to inject data into the plugin on the before* plugins and use the data for your -own business login in the after* events, for example - -``` -/** - * Forced login using a beforeLogin event - */ -public function eventLogin() -{ - $this->eventManager()->on(UsersAuthComponent::EVENT_BEFORE_LOGIN, function () { - //the callback function should return the user data array to force login - return [ - 'id' => 1337, - 'username' => 'forceLogin', - 'email' => 'event@example.com', - 'active' => true, - ]; - }); - $this->login(); - $this->render('login'); -} - -/** - * beforeRegister event - */ -public function eventRegister() -{ - $this->eventManager()->on(UsersAuthComponent::EVENT_BEFORE_REGISTER, function ($event) { - //the callback function should return the user data array to force register - return $event->data['usersTable']->newEntity([ - 'username' => 'forceEventRegister', - 'email' => 'eventregister@example.com', - 'password' => 'password', - 'active' => true, - 'tos' => true, - ]); - }); - $this->register(); - $this->render('register'); -} -``` diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md deleted file mode 100644 index fec58928a..000000000 --- a/Docs/Documentation/Extending-the-Plugin.md +++ /dev/null @@ -1,219 +0,0 @@ -Extending the Plugin -==================== - -Extending the Model (Table/Entity) -------------------- - -Create a new Table and Entity in your app, matching the table you want to use for storing the -users data. Check the initial users migration to know the default columns expected in the table. -If your column names doesn't match the columns in your current table, you could use the Entity to -match the colums using accessors & mutators as described here http://book.cakephp.org/3.0/en/orm/entities.html#accessors-mutators - -Example: we are going to use a custom table ```my_users``` in our application , which has a field named ``is_active`` instead of the default ``active``. -* Create a new Table under src/Model/Table/MyUsersTable.php - -```php -namespace App\Model\Table; - -use CakeDC\Users\Model\Table\UsersTable; - -/** - * Application specific Users Table with non plugin conform field(s) - */ -class MyUsersTable extends UsersTable -{ -} -``` - -* Create a new Entity under src/Model/Entity/MyUser.php - -```php -namespace App\Model\Entity; - -use CakeDC\Users\Model\Entity\User; - -/** - * Application specific User Entity with non plugin conform field(s) - */ -class MyUser extends User -{ - /** - * Map CakeDC's User.active field to User.is_active when getting - * - * @return mixed The value of the mapped property. - */ - protected function _getActive() - { - return $this->_properties['is_active']; - } - - /** - * Map CakeDC's User.active field to User.is_active when setting - * - * @param mixed $value The value to set. - * @return static - */ - protected function _setActive($value) - { - $this->set('is_active', $value); - return $value; - } -} -``` - -* Pass the new table configuration to Users Plugin Configuration - -config/bootstrap.php -``` -Configure::write('Users.config', ['users']); -Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); -``` - -Then in your config/users.php -``` -return [ - 'Users.table' => 'MyUsers', -]; -``` - -Now the Users Plugin will use MyUsers Table and Entity to register and login user in. Use the -Entity as shown above to match your own columns in case they don't match the default column names: - -```sql -CREATE TABLE IF NOT EXISTS `users` ( - `id` char(36) NOT NULL, - `username` varchar(255) NOT NULL, - `email` varchar(255) DEFAULT NULL, - `password` varchar(255) NOT NULL, - `first_name` varchar(50) DEFAULT NULL, - `last_name` varchar(50) DEFAULT NULL, - `token` varchar(255) DEFAULT NULL, - `token_expires` datetime DEFAULT NULL, - `api_token` varchar(255) DEFAULT NULL, - `activation_date` datetime DEFAULT NULL, - `tos_date` datetime DEFAULT NULL, - `active` int(1) NOT NULL DEFAULT '0', - `is_superuser` int(1) NOT NULL DEFAULT '0', - `role` varchar(255) DEFAULT 'user', - `created` datetime NOT NULL, - `modified` datetime NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -``` - -Extending the Controller -------------------- - -You want to use one of your controllers to handle all the users features in your app, and keep the -login/register/etc actions from Users Plugin, - -First create a new controller class: - -```php - [ - // ... - // Controller used to manage users plugin features & actions - 'controller' => 'MyUsers', - // ... -``` - -Note you'll need to **copy the Plugin templates** you need into your project src/Template/MyUsers/[action].ctp - -Extending the Features in your controller ------------------------------ - -You could use a new Trait. For example, you want to add an 'impersonate' feature - -```php -getUsersTable()->find() - ->where(['id' => $userId]) - ->hydrate(false) - ->first(); - $this->Auth->setUser($user); - return $this->redirect('/'); - } -} -``` -Updating the Templates -------------------- - -Use the standard CakePHP conventions to override Plugin views using your application views -http://book.cakephp.org/3.0/en/plugins.html#overriding-plugin-templates-from-inside-your-application - -`{project_dir}/src/Template/Plugin/CakeDC/Users/Users/{templates_in_here}` - -Updating the Emails -------------------- - -Extend the `\CakeDC\Users\Mailer\UsersMailer` class and override the email configuration to change the way the -emails are sent by the Plugin. We currently have: -* validation, sent with a link to validate new users registered -* resetPassword, sent with a link to access the reset password feature -* socialAccountValidation, sent with a link to validate the social account used for login - -Example, to override the validation email you would need to: -* Create a new class in your application -```php -namespace App\Mailer; - -use Cake\Datasource\EntityInterface; -use CakeDC\Users\Mailer\UsersMailer; - -class MyUsersMailer extends UsersMailer -{ - public function resetPassword(EntityInterface $user) - { - parent::resetPassword($user); - $this->setSubject('This is the new subject'); - $this->setTemplate('custom-template-in-app-namespace'); - } -} -``` -* Configure the Plugin to use this new mailer class in bootstrap or users.php -`Configure::write('Users.Email.mailerClass', \App\Mailer\MyUsersMailer::class);` - -* Create the file `src/Template/Email/text/custom_template_in_app_namespace.ctp` -with your custom contents. Note you can also prepare an html version of the file, -change the template, or do any other customization in the `MyUsersMailer` method. - - diff --git a/Docs/Documentation/Google-Two-Factor-Authenticator.md b/Docs/Documentation/Google-Two-Factor-Authenticator.md deleted file mode 100644 index 99245ce76..000000000 --- a/Docs/Documentation/Google-Two-Factor-Authenticator.md +++ /dev/null @@ -1,36 +0,0 @@ -Google Two Factor Authenticator -=============================== - -Installation ------------- -To enable this feature you need to - -``` -composer require robthree/twofactorauth -``` - -Setup ------ - -Enable google authenticator in your bootstrap.php file: - -Config/bootstrap.php -``` -Configure::write('Users.GoogleAuthenticator.login', true); -``` - -How does it work ----------------- -When the user log-in, he is requested (image 1) to inform the current validation -code for your site in Google Authentation app (image 2), if this is the first -time he access he need to add your site to Google Authentation by reading -the QR code shown (image 1). - -1) Validation code page - - - -2) Google Authentation app - - - diff --git a/Docs/Documentation/GoogleAuthenticator/App.png b/Docs/Documentation/GoogleAuthenticator/App.png deleted file mode 100644 index dd47e98453d50c1aa3c68ed9195c272c5731daf3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52261 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�AN)pabKi!7 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 diff --git a/Docs/Documentation/GoogleAuthenticator/FirstLogin.png b/Docs/Documentation/GoogleAuthenticator/FirstLogin.png deleted file mode 100644 index 18d4ce76e69dc9747ea629fe15e6d99ec1feefe5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21106 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 a6ZcZ8*^Y-HCTsshp^m2h#k}*@5B?853l{GH diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md deleted file mode 100644 index bd8a34803..000000000 --- a/Docs/Documentation/Installation.md +++ /dev/null @@ -1,115 +0,0 @@ -Installation -============ - -Composer ------- - -``` -composer require cakedc/users -``` - -If you want to use social login features... - -``` -composer require league/oauth2-facebook:@stable -composer require league/oauth2-instagram:@stable -composer require league/oauth2-google:@stable -composer require league/oauth2-linkedin:@stable -composer require league/oauth1-client:@stable -``` - -NOTE: you'll need to enable social login in your bootstrap.php file if you want to use it, social -login is disabled by default. Check the [Configuration](Configuration.md#configuration-for-social-login) page for more details. - -``` -Configure::write('Users.Social.login', true); //to enable social login -``` - -If you want to use reCaptcha features... - -``` -composer require google/recaptcha:@stable -``` - -NOTE: you'll need to configure the reCaptcha key and secret, check the [Configuration](Configuration.md) -page for more details. - -If you want to use Google Authenticator features... - -``` -composer require robthree/twofactorauth:"^1.5.2" -``` - -NOTE: you'll need to enable `Users.GoogleAuthenticator.login` - -``` -Configure::write('Users.GoogleAuthenticator.login', true); -``` - -Load the Plugin ------------ - -Ensure the Users Plugin is loaded in your config/bootstrap.php file - -``` -Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); -``` - -Creating Required Tables ------------------------- -If you want to use the Users tables to store your users and social accounts: - -``` -bin/cake migrations migrate -p CakeDC/Users -``` - -Note you don't need to use the provided tables, you could customize the table names, fields etc in your -application and then use the plugin configuration to use your own tables instead. Please refer to the [Extending the Plugin](Extending-the-Plugin.md) -section to check all the customization options - -Customization ----------- - -config/bootstrap.php -``` -Configure::write('Users.config', ['users']); -Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); -Configure::write('Users.Social.login', true); //to enable social login -``` - -If you want to use social login, then in your config/users.php -``` -return [ - 'OAuth.providers.facebook.options.clientId' => 'YOUR APP ID', - 'OAuth.providers.facebook.options.clientSecret' => 'YOUR APP SECRET', - 'OAuth.providers.twitter.options.clientId' => 'YOUR APP ID', - 'OAuth.providers.twitter.options.clientSecret' => 'YOUR APP SECRET', - //etc -]; -``` -IMPORTANT: Remember you'll need to configure your social login application **callback url** to use the provider specific endpoint, for example: -* Facebook App Callback URL --> `http://yourdomain.com/auth/facebook` -* Twitter App Callback URL --> `http://yourdomain.com/auth/twitter` -* Google App Callback URL --> `http://yourdomain.com/auth/google` -* etc. - -Note: using social authentication is not required. - -For more details, check the Configuration doc page - -Load the UsersAuth Component ---------------------- - -Load the Component in your src/Controller/AppController.php, and use the passed Component configuration to customize the Users Plugin: - -``` - public function initialize() - { - parent::initialize(); - - // Important: add the 'enableBeforeRedirect' config or or disable deprecation warnings - $this->loadComponent('RequestHandler', ['enableBeforeRedirect' => false]); - $this->loadComponent('Flash'); - $this->loadComponent('CakeDC/Users.UsersAuth'); - } -``` diff --git a/Docs/Documentation/Migration/4.x-5.0.md b/Docs/Documentation/Migration/4.x-5.0.md deleted file mode 100644 index 9aba06bd3..000000000 --- a/Docs/Documentation/Migration/4.x-5.0.md +++ /dev/null @@ -1,56 +0,0 @@ -Migration 4.x to 5.0 -====================== - -5.0 is compatible with CakePHP ^3.4 and refactored some Auth objects into a new plugin -* Fix your Users configuration file, usually under `config/users.php` for Auth object references - -in `config/users.php` - -```php -$config = [ - // ... - 'Auth' => [ - // ... - 'authenticate' => [ - 'all' => [ - 'finder' => 'auth', - ], - 'CakeDC/Auth.ApiKey', - 'CakeDC/Auth.RememberMe', - 'Form', - ], - 'authorize' => [ - 'CakeDC/Auth.Superuser', - 'CakeDC/Auth.SimpleRbac', - ], - // ... -``` - -* Add a new configuration key to specify the controller name you are using to handle auth in your project - -in `config/users.php` - -```php -$config = [ - 'Users' => [ - // ... - // Controller used to manage users plugin features & actions - 'controller' => 'CakeDC/Users.Users', - // ... -``` - -* If you are using simple RBAC, set `CakeDC/Auth.SimpleRbac.permissions` configuration key to `null` if you want to load permissions from the file `config/permissions.php`. - -in `config/users.php` - -```php -$config = [ - 'Auth.authorize' => [ - 'CakeDC/Auth.SimpleRbac' => [ - 'autoload_config' => 'permissions', - 'permissions' => null, - ], - ], -``` - -If the value is false or empty array, now it is assumed there is no permissions for the user. \ No newline at end of file diff --git a/Docs/Documentation/Migration/6.x-7.0.md b/Docs/Documentation/Migration/6.x-7.0.md deleted file mode 100644 index 3258e398f..000000000 --- a/Docs/Documentation/Migration/6.x-7.0.md +++ /dev/null @@ -1,18 +0,0 @@ -Migration 6.x to 7.0 -====================== - -7.0 is compatible with CakePHP ^3.6 and the plugin code was updated to remove all deprecations. - -* Add 'enableBeforeRedirect' configuration option to RequestHandler component load in your `src/Controller/AppController.php` file - -``` - public function initialize() - { - parent::initialize(); - - // Important: add the 'enableBeforeRedirect' config or or disable deprecation warnings - $this->loadComponent('RequestHandler', ['enableBeforeRedirect' => false]); - $this->loadComponent('Flash'); - $this->loadComponent('CakeDC/Users.UsersAuth'); - } -``` diff --git a/Docs/Documentation/Overview.md b/Docs/Documentation/Overview.md deleted file mode 100644 index cc47d0159..000000000 --- a/Docs/Documentation/Overview.md +++ /dev/null @@ -1,19 +0,0 @@ -Overview -======== - -You can use the plugin as it comes if you're happy with it or, more common, extend your app specific user implementation from the plugin. - -The plugin itself is already capable of: - -* User registration -* Account verification by a token sent via email -* User login (email / password) -* Social login (Twitter, Facebook, Google, Instagram, LinkedIn) -* Password reset based on requesting a token by email and entering a new password -* User management (add / edit / delete) -* Simple roles management -* Simple Rbac and SuperUser Authorize -* RememberMe using cookie feature -* reCaptcha for user registration and login -* Two Factor authentication - diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md deleted file mode 100644 index 937039366..000000000 --- a/Docs/Documentation/SocialAuthenticate.md +++ /dev/null @@ -1,97 +0,0 @@ -SocialAuthenticate -============= - -We currently support the following providers to perform login as well as to link an existing account: - -* Facebook -* Twitter -* Google -* LinkedIn -* Instagram -* Amazon - -Please [contact us](https://cakedc.com/contact) if you need to support another provider. - -Setup ---------------------- - -Create the Facebook/Twitter applications you want to use and setup the configuration like this: - -Config/bootstrap.php -``` -Configure::write('OAuth.providers.facebook.options.clientId', 'YOUR APP ID'); -Configure::write('OAuth.providers.facebook.options.clientSecret', 'YOUR APP SECRET'); - -Configure::write('OAuth.providers.twitter.options.clientId', 'YOUR APP ID'); -Configure::write('OAuth.providers.twitter.options.clientSecret', 'YOUR APP SECRET'); -``` - -You can also change the default settings for social authenticate: - -``` -Configure::write('Users', [ - 'Email' => [ - //determines if the user should include email - 'required' => true, - //determines if registration workflow includes email validation - 'validate' => true, - ], - 'Social' => [ - //enable social login - 'login' => false, - ], - 'Key' => [ - 'Session' => [ - //session key to store the social auth data - 'social' => 'Users.social', - ], - //form key to store the social auth data - 'Form' => [ - 'social' => 'social' - ], - 'Data' => [ - //data key to store email coming from social networks - 'socialEmail' => 'info.email', - ], - ], -]); -``` - -If email is required and the social network does not return the user email then the user will be required to input the email. Additionally, validation could be enabled, in that case the user will be asked to validate the email before be able to login. There are some cases where the email address already exists onto database, if so, the user will receive an email and will be asked to validate the social account in the app. It is important to take into account that the user account itself will remain active and accessible by other ways (other social network account or username/password). - -In most situations you would not need to change any Oauth setting besides applications details. - -For new facebook aps you must use the graphApiVersion 2.8 or greater: - -``` -Configure::write('OAuth.providers.facebook.options.graphApiVersion', 'v2.8'); -``` - -User Helper ---------------------- - -You can use the helper included with the plugin to create Facebook/Twitter buttons: - -In templates -``` -$this->User->facebookLogin(); - -$this->User->twitterLogin(); -``` - -We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. - -Social Authentication was inspired by [UseMuffin/OAuth2](https://github.com/UseMuffin/OAuth2) library. - -Custom username field ---------------------- - -In your customized users table, add the SocialBehavior with the following configuration: - -```php -$this->addBehavior('CakeDC.Users/Social', [ - 'username' => 'email' -]); -``` - -By default it will use `username` field. diff --git a/Docs/Documentation/Translations.md b/Docs/Documentation/Translations.md deleted file mode 100644 index 41abc4e08..000000000 --- a/Docs/Documentation/Translations.md +++ /dev/null @@ -1,17 +0,0 @@ -Translations -============ - -The Plugin is translated into several languages: - -* Swedish (sv) by @digitalfotografen -* Spanish (es) by @florenciohernandez -* Brazillian Portuguese (pt_BR) by @andtxr -* French (fr_FR) by @jtraulle -* Polish (pl) by @joulbex -* Hungarian (hu_HU) by @rrd108 -* Italian (it) by @arturmamedov -* Turkish (tr_TR) by @sayinserdar - -**Note:** To overwrite the plugin translations, create a file inside your project 'src/Locale/{$lang}/' folder, with the name 'Users.po' and add the strings with the new translations. - -Remember to clean the translations cache! diff --git a/Docs/Documentation/UserHelper.md b/Docs/Documentation/UserHelper.md deleted file mode 100644 index 920f37f98..000000000 --- a/Docs/Documentation/UserHelper.md +++ /dev/null @@ -1,85 +0,0 @@ -UserHelper -============= - -The User Helper has some methods that may be needed if you want to improve your templates and add features to your app in an easy way. - -Setup ---------------- - -Enable the Helper in `src/view/AppView.php`: -```php -class AppView extends View -{ - public function initialize() - { - parent::initialize(); - $this->loadHelper('CakeDC/Users.User'); - } -} -``` - -Social Login ------------------ - -You can use the helper included with the plugin to create Facebook/Twitter buttons: - -In templates -```php -echo $this->User->socialLogin($provider); //provider is 'facebook', 'twitter', etc -``` - -We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. - -Connect Social Account ------------------ - -You can use the helper included with the plugin to create some 'Connect with Facebook/Twitter' buttons: - -In templates, call socialConnectLinkList method to get links for all social providers enabled -```php -echo $this->User->socialConnectLinkList($user->social_accounts); -``` - -We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. - -The user must be allowed to access the urls "/link-social/[provider]" and "/callback-link-social/[provider]". - -Logout link ------------------ - -It allows to add a logout link anywhere in the app. - -```php -$this->User->logout(); -``` - -RBAC link ------------------ - -This function validates if you have access to a link and it displays it based on that. - -```php -$this->User->link(); -``` - -Welcome and profile link ------------------ - -It displays a welcome message for the user including the name and a link to the profile page - -```php -$this->User->welcome(); -``` - -reCaptcha ------------------ - -Handles the reCaptcha input display: - -```php -$this->User->addReCaptchaScript(); - -$this->User->addReCaptcha(); -``` - -Note reCaptcha script is added to script block when `addReCaptcha` method is called. diff --git a/Docs/Home.md b/Docs/Home.md deleted file mode 100644 index 378d61db9..000000000 --- a/Docs/Home.md +++ /dev/null @@ -1,32 +0,0 @@ -Home -==== - -The **Users** Plugin allow users to register and login, manage their profile, etc. It also allows admins to manage the users. - -The plugin is thought as a base to extend your app specific users controller and model from. - -That it works out of the box doesn't mean it is thought to be used exactly like it is but to provide you a kick start. - -Documentation -------------- - -* [Overview](Documentation/Overview.md) -* [Installation](Documentation/Installation.md) -* [Configuration](Documentation/Configuration.md) -* [SimpleRbacAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SimpleRbacAuthorize.md) -* [SuperuserAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SuperuserAuthorize.md) -* [ApiKeyAuthenticate](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/ApiKeyAuthenticate.md) -* [SocialAuthenticate](Documentation/SocialAuthenticate.md) -* [Google Authenticator](Documentation/Google-Two-Factor-Authenticator.md) -* [UserHelper](Documentation/UserHelper.md) -* [Events](Documentation/Events.md) -* [Extending the Plugin](Documentation/Extending-the-Plugin.md) -* [Translations](Documentation/Translations.md) - -Migration guides ----------------- - -* [4.x to 5.0](Documentation/Migration/4.x-5.0.md) -* [6.x to 7.0](Documentation/Migration/6.x-7.0.md) - - diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 5448b2520..000000000 --- a/LICENSE.txt +++ /dev/null @@ -1,26 +0,0 @@ -The MIT License - -Copyright 2009-2018 -Cake Development Corporation -1785 E. Sahara Avenue, Suite 490-423 -Las Vegas, Nevada 89104 -Phone: +1 702 425 5085 -https://www.cakedc.com - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index cc71ac418..000000000 --- a/README.md +++ /dev/null @@ -1,74 +0,0 @@ -CakeDC Users Plugin -=================== - -[![Build Status](https://secure.travis-ci.org/CakeDC/users.png?branch=master)](http://travis-ci.org/CakeDC/users) -[![Coverage Status](https://img.shields.io/codecov/c/gh/CakeDC/users.svg?style=flat-square)](https://codecov.io/gh/CakeDC/users) -[![Downloads](https://poser.pugx.org/CakeDC/users/d/total.png)](https://packagist.org/packages/CakeDC/users) -[![Latest Version](https://poser.pugx.org/CakeDC/users/v/stable.png)](https://packagist.org/packages/CakeDC/users) -[![License](https://poser.pugx.org/CakeDC/users/license.svg)](https://packagist.org/packages/CakeDC/users) - -Versions and branches ---------------------- - -| CakePHP | CakeDC Users Plugin | Tag | Notes | -| :-------------: | :------------------------: | :--: | :---- | -| ^3.6 | [master](https://github.com/cakedc/users/tree/master) | 8.0.2 | stable | -| ^3.6 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | -| 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.3 | [4.x](https://github.com/cakedc/users/tree/4.x) | 4.2.0 | stable | -| 2.x | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.2.0 |stable | - -The **Users** plugin is back! - -It covers the following features: -* User registration -* Login/logout -* Social login (Facebook, Twitter, Instagram, Google, Linkedin, etc) -* Simple RBAC via https://github.com/CakeDC/auth -* Remember me (Cookie) via https://github.com/CakeDC/auth -* Manage user's profile -* Admin management - -The plugin is here to provide users related features following 2 approaches: -* Quick drop-in working solution for users login/registration. Get users working in 5 minutes. -* Extensible solution for a bigger/custom application. You'll be able to extend: - * UsersAuth Component - * Use your own UsersTable - * Use your own Controller - -On the previous versions of the plugin, extensibility was an issue, and one of the main -objectives of the 3.0 rewrite is to guarantee all the pieces could be extended/reused as -easily. - -Another decision made was limiting the plugin dependencies on other packages as much as possible. - -Requirements ------------- - -* CakePHP 3.6.0+ -* PHP 5.6+ - -Documentation -------------- - -For documentation, as well as tutorials, see the [Docs](Docs/Home.md) directory of this repository. - -Support -------- - -For bugs and feature requests, please use the [issues](https://github.com/CakeDC/users/issues) section of this repository. - -Commercial support is also available, [contact us](https://www.cakedc.com/contact) for more information. - -Contributing ------------- - -This repository follows the [CakeDC Plugin Standard](https://www.cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](https://www.cakedc.com/contribution-guidelines) for detailed instructions. - -License -------- - -Copyright 2017 Cake Development Corporation (CakeDC). All rights reserved. - -Licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) License. Redistributions of the source code included in this repository must retain the copyright notice found in each file. diff --git a/composer.json b/composer.json index 2609599e4..4bcf8b3ef 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "cakedc/auth": "^3.0" }, "require-dev": { - "phpunit/phpunit": "^5.0", + "phpunit/phpunit": "^5.7|^6.0", "cakephp/cakephp-codesniffer": "^2.0", "league/oauth2-facebook": "@stable", "league/oauth2-instagram": "@stable", diff --git a/config/Migrations/20150513201111_initial.php b/config/Migrations/20150513201111_initial.php deleted file mode 100644 index 55b00f094..000000000 --- a/config/Migrations/20150513201111_initial.php +++ /dev/null @@ -1,152 +0,0 @@ -table('users', ['id' => false, 'primary_key' => ['id']]); - $table - ->addColumn('id', 'uuid', [ - 'null' => false, - ]) - ->addColumn('username', 'string', [ - 'limit' => 255, - 'null' => false, - ]) - ->addColumn('email', 'string', [ - 'default' => null, - 'limit' => 255, - 'null' => true, - ]) - ->addColumn('password', 'string', [ - 'limit' => 255, - 'null' => false, - ]) - ->addColumn('first_name', 'string', [ - 'default' => null, - 'limit' => 50, - 'null' => true, - ]) - ->addColumn('last_name', 'string', [ - 'default' => null, - 'limit' => 50, - 'null' => true, - ]) - ->addColumn('token', 'string', [ - 'default' => null, - 'limit' => 255, - 'null' => true, - ]) - ->addColumn('token_expires', 'datetime', [ - 'default' => null, - 'null' => true, - ]) - ->addColumn('api_token', 'string', [ - 'default' => null, - 'limit' => 255, - 'null' => true, - ]) - ->addColumn('activation_date', 'datetime', [ - 'default' => null, - 'null' => true, - ]) - ->addColumn('tos_date', 'datetime', [ - 'default' => null, - 'null' => true, - ]) - ->addColumn('active', 'boolean', [ - 'default' => false, - 'null' => false, - ]) - ->addColumn('is_superuser', 'boolean', [ - 'default' => false, - 'null' => false, - ]) - ->addColumn('role', 'string', [ - 'default' => 'user', - 'limit' => 255, - 'null' => true, - ]) - ->addColumn('created', 'datetime', [ - 'null' => false, - ]) - ->addColumn('modified', 'datetime', [ - 'null' => false, - ]) - ->create(); - - $table = $this->table('social_accounts', ['id' => false, 'primary_key' => ['id']]); - $table - ->addColumn('id', 'uuid', [ - 'null' => false, - ]) - ->addColumn('user_id', 'uuid', [ - 'null' => false, - ]) - ->addColumn('provider', 'string', [ - 'limit' => 255, - 'null' => false, - ]) - ->addColumn('username', 'string', [ - 'default' => null, - 'limit' => 255, - 'null' => true, - ]) - ->addColumn('reference', 'string', [ - 'limit' => 255, - 'null' => false, - ]) - ->addColumn('avatar', 'string', [ - 'default' => null, - 'limit' => 255, - 'null' => true, - ]) - ->addColumn('description', 'text', [ - 'default' => null, - 'null' => true, - ]) - ->addColumn('link', 'string', [ - 'limit' => 255, - 'null' => false, - ]) - ->addColumn('token', 'string', [ - 'limit' => 500, - 'null' => false, - ]) - ->addColumn('token_secret', 'string', [ - 'default' => null, - 'limit' => 500, - 'null' => true, - ]) - ->addColumn('token_expires', 'datetime', [ - 'default' => null, - 'null' => true, - ]) - ->addColumn('active', 'boolean', [ - 'default' => true, - 'null' => false, - ]) - ->addColumn('data', 'text', [ - 'null' => false, - ]) - ->addColumn('created', 'datetime', [ - 'null' => false, - ]) - ->addColumn('modified', 'datetime', [ - 'null' => false, - ]) - ->addForeignKey('user_id', 'users', 'id', array('delete' => 'CASCADE', 'update' => 'CASCADE')) - ->create(); - } -} diff --git a/config/Migrations/20161031101316_AddSecretToUsers.php b/config/Migrations/20161031101316_AddSecretToUsers.php deleted file mode 100644 index 27df2506c..000000000 --- a/config/Migrations/20161031101316_AddSecretToUsers.php +++ /dev/null @@ -1,43 +0,0 @@ -table('users'); - /** - * Limiting secret field to 32 chars - * @see https://en.wikipedia.org/wiki/Google_Authenticator#Technical_description - */ - $table->addColumn('secret', 'string', [ - 'after' => 'activation_date', - 'default' => null, - 'limit' => 32, - 'null' => true, - ]); - $table->addColumn('secret_verified', 'boolean', [ - 'after' => 'secret', - 'default' => null, - 'null' => true, - ]); - $table->update(); - } -} diff --git a/config/Migrations/schema-dump-default.lock b/config/Migrations/schema-dump-default.lock deleted file mode 100644 index f4f542a7347d46742ad58d60b1b7e1b6ff262461..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7938 zcmds6O>@&Q5aqY{$f;=wALGZ$zR*r0W9W$*%)3m47 z*;v}|eQzVhskn7wu@s3jnU+N=v&=MQ?UM8F;_Or;pX8Og_$+I=l1^Rx$bPAfy!a_s zg=+s##5+3SgGgSzewE^Dg-XsRPQ=HH_IsHrnoWsIB;Aeoag)yJ(VzB4B=w)lAB2CK zhD1)h6-lAW%lcPx{tb_iluc12=PPl7$9E#h)mk=1-HP#?naxI(cy{7MB=qOKNXU+# z{%|@3dRJCu+G$hLdw2ez#wnW~i$2h~vgTUn%94XVkh>xW!7Hw|y1ZmA(&BWvgoXEU zQ&Gse3tLmK-=~+VR2J!wX*zbEFP%VIt@VvU^t@+b33;}Z8(g-RC5u+6alj8`3DU-@ zwX&+r_BCZPcMoI=@<(2yzV}V8rw$3VmRz~a>Zl-cBA@=H5zl%+43RA6&#bl_ z;SEWFpVdIPN(3|f0DYW>-Xa#HDk8WOLESsLlZwxYE^ghJT(9-&Z}t6{3C10c ze_`A+JaT3|A{4LB?xMpwS)&NQyHy?co6b zLe~s>${}ub;0#@aaZdyaBpAc(-5p(ybBNkxrbLvb_S{Ieya@_aR&S*JLz%=Ch^3(g zbgU<+uq8e_ZwD=cm=Uv7uhv&7TAYNwa01*NxDqa08>{rCZ<=_DX;!!pAICN?z>GR5 z>!$-4Ve1_jPT$0bT2SX7sM=JN4#Bt5Wik)LBUgo*5C#4gxp&J5jYn-k0Urx+Jza)F zzm%o<{E_ZM6~Qhr7LW4U0F5{c1rBNKIjP!I#`+i$Q-q{9Y%h-6AJaFM*yDbBY@K!t z#CFh{9)fC)j!44uSVL%V|GmtZgfovbsYl?9=7@Cex3PY3KVxQ3U1Y7TtJ8;*`z2!l zPaPHXmqNY>OHd{=DA}mmpE@8%%wdo#veM~`@G`Q+LpncL({{R##};}P!+~L@vz_c@ z*34lOKxT93_}MA&LbP0%)agJC-|yM|S|Pnwc9I+cqD6Q*LZy%CVg$A}?)c&!XvR1d z@9QScYk}58auT5HtltQTLur?~rc#zLG69kQy298`J*2$F^5j3mBVS6bwSmqY=63^P zGJ!je{e16^#PgtA%*^RXxb>OrH)0ynhH(3P8cd*Qwup`G0D6SY1bC^(tW3sHAQKOP z6%+PYg$Z^{f3_j;lrS2@{D579ZFEF5VRpRV4xgxL^Q8ye(s$2Yhle)CUmSN5{*A7f rnO<>KjBXsHCzBF4-m>m!qeA-*2;i(8+m5hqdCYA`q}Jh<0e61^4bj5{ diff --git a/config/bootstrap.php b/config/bootstrap.php deleted file mode 100644 index 42d2bb0c2..000000000 --- a/config/bootstrap.php +++ /dev/null @@ -1,49 +0,0 @@ -each(function ($file) { - Configure::load($file); -}); - -TableRegistry::getTableLocator()->setConfig('Users', ['className' => Configure::read('Users.table')]); -TableRegistry::getTableLocator()->setConfig('CakeDC/Users.Users', ['className' => Configure::read('Users.table')]); - -if (Configure::check('Users.auth')) { - Configure::write('Auth.authenticate.all.userModel', Configure::read('Users.table')); -} - -if (Configure::read('Users.Social.login') && php_sapi_name() != 'cli') { - try { - EventManager::instance()->on(\CakeDC\Users\Controller\Component\UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, [new \CakeDC\Users\Controller\UsersController(), 'failedSocialLoginListener']); - } catch (MissingPluginException $e) { - Log::error($e->getMessage()); - } -} - -$oauthPath = Configure::read('OAuth.path'); -if (is_array($oauthPath)) { - Router::scope('/auth', function ($routes) use ($oauthPath) { - $routes->connect( - '/:provider', - $oauthPath, - ['provider' => implode('|', array_keys(Configure::read('OAuth.providers')))] - ); - }); -} diff --git a/config/permissions.php b/config/permissions.php deleted file mode 100644 index 79a4ae957..000000000 --- a/config/permissions.php +++ /dev/null @@ -1,91 +0,0 @@ - 'role' | ['roles'] | '*' - * 'prefix' => 'Prefix' | , (default = null) - * 'plugin' => 'Plugin' | , (default = null) - * 'controller' => 'Controller' | ['Controllers'] | '*', - * 'action' => 'action' | ['actions'] | '*', - * 'allowed' => true | false | callback (default = true) - * ] - * You could use '*' to match anything - * 'allowed' will be considered true if not defined. It allows a callable to manage complex - * permissions, like this - * 'allowed' => function (array $user, $role, Request $request) {} - * - * Example, using allowed callable to define permissions only for the owner of the Posts to edit/delete - * - * (remember to add the 'uses' at the top of the permissions.php file for Hash, TableRegistry and Request - [ - 'role' => ['user'], - 'controller' => ['Posts'], - 'action' => ['edit', 'delete'], - 'allowed' => function(array $user, $role, Request $request) { - $postId = Hash::get($request->params, 'pass.0'); - $post = TableRegistry::getTableLocator()->get('Posts')->get($postId); - $userId = Hash::get($user, 'id'); - if (!empty($post->user_id) && !empty($userId)) { - return $post->user_id === $userId; - } - return false; - } - ], - */ - -return [ - 'CakeDC/Auth.permissions' => [ - //admin role allowed to all the things - [ - 'role' => 'admin', - 'prefix' => '*', - 'extension' => '*', - 'plugin' => '*', - 'controller' => '*', - 'action' => '*', - ], - //specific actions allowed for the all roles in Users plugin - [ - 'role' => '*', - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => ['profile', 'logout', 'linkSocial', 'callbackLinkSocial'], - ], - [ - 'role' => '*', - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'resetGoogleAuthenticator', - 'allowed' => function (array $user, $role, \Cake\Http\ServerRequest $request) { - $userId = \Cake\Utility\Hash::get($request->getAttribute('params'), 'pass.0'); - if (!empty($userId) && !empty($user)) { - return $userId === $user['id']; - } - - return false; - } - ], - //all roles allowed to Pages/display - [ - 'role' => '*', - 'controller' => 'Pages', - 'action' => 'display', - ], - ] -]; diff --git a/config/routes.php b/config/routes.php deleted file mode 100644 index f19f356a3..000000000 --- a/config/routes.php +++ /dev/null @@ -1,52 +0,0 @@ - '/users'], function ($routes) { - $routes->fallbacks('DashedRoute'); -}); - -Router::connect('/auth/twitter', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'twitterLogin', - 'provider' => 'twitter' -]); -Router::connect('/accounts/validate/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'SocialAccounts', - 'action' => 'validate' -]); -// Google Authenticator related routes -if (Configure::read('Users.GoogleAuthenticator.login')) { - Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']); - - Router::connect('/resetGoogleAuthenticator', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'resetGoogleAuthenticator' - ]); -} - -Router::connect('/profile/*', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); -Router::connect('/login', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); -Router::connect('/logout', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout']); -Router::connect('/link-social/*', [ - 'controller' => 'Users', - 'action' => 'linkSocial', - 'plugin' => 'CakeDC/Users', -]); -Router::connect('/callback-link-social/*', [ - 'controller' => 'Users', - 'action' => 'callbackLinkSocial', - 'plugin' => 'CakeDC/Users', -]); diff --git a/config/users.php b/config/users.php deleted file mode 100644 index 45a15f5ec..000000000 --- a/config/users.php +++ /dev/null @@ -1,206 +0,0 @@ - [ - // Table used to manage users - 'table' => 'CakeDC/Users.Users', - // Controller used to manage users plugin features & actions - 'controller' => 'CakeDC/Users.Users', - // configure Auth component - 'auth' => true, - // Password Hasher - 'passwordHasher' => '\Cake\Auth\DefaultPasswordHasher', - // token expiration, 1 hour - 'Token' => ['expiration' => 3600], - 'Email' => [ - // determines if the user should include email - 'required' => true, - // determines if registration workflow includes email validation - 'validate' => true, - ], - 'Registration' => [ - // determines if the register is enabled - 'active' => true, - // determines if the reCaptcha is enabled for registration - 'reCaptcha' => true, - // allow a logged in user to access the registration form - 'allowLoggedIn' => false, - //ensure user is active (confirmed email) to reset his password - 'ensureActive' => false, - // default role name used in registration - 'defaultRole' => 'user', - ], - 'reCaptcha' => [ - // reCaptcha key goes here - 'key' => null, - // reCaptcha secret - 'secret' => null, - // use reCaptcha in registration - 'registration' => false, - // use reCaptcha in login, valid values are false, true - 'login' => false, - ], - 'Tos' => [ - // determines if the user should include tos accepted - 'required' => true, - ], - 'Social' => [ - // enable social login - 'login' => false, - // enable social login - 'authenticator' => 'CakeDC/Users.Social', - ], - 'GoogleAuthenticator' => [ - // enable Google Authenticator - 'login' => false, - 'issuer' => null, - // The number of digits the resulting codes will be - 'digits' => 6, - // The number of seconds a code will be valid - 'period' => 30, - // The algorithm used - 'algorithm' => 'sha1', - // QR-code provider (more on this later) - 'qrcodeprovider' => null, - // Random Number Generator provider (more on this later) - 'rngprovider' => null - ], - 'Profile' => [ - // Allow view other users profiles - 'viewOthers' => true, - 'route' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], - ], - 'Key' => [ - 'Session' => [ - // session key to store the social auth data - 'social' => 'Users.social', - // userId key used in reset password workflow - 'resetPasswordUserId' => 'Users.resetPasswordUserId', - ], - // form key to store the social auth data - 'Form' => [ - 'social' => 'social' - ], - 'Data' => [ - // data key to store the users email - 'email' => 'email', - // data key to store email coming from social networks - 'socialEmail' => 'info.email', - // data key to check if the remember me option is enabled - 'rememberMe' => 'remember_me', - ], - ], - // Avatar placeholder - 'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'], - 'RememberMe' => [ - // configure Remember Me component - 'active' => true, - 'checked' => true, - 'Cookie' => [ - 'name' => 'remember_me', - 'Config' => [ - 'expires' => '1 month', - 'httpOnly' => true, - ] - ] - ], - ], - 'GoogleAuthenticator' => [ - 'checker' => \CakeDC\Users\Auth\DefaultTwoFactorAuthenticationChecker::class, - 'verifyAction' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'verify', - 'prefix' => false, - ], - ], - // default configuration used to auto-load the Auth Component, override to change the way Auth works - 'Auth' => [ - 'loginAction' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - 'prefix' => false - ], - 'authenticate' => [ - 'all' => [ - 'finder' => 'auth', - ], - 'CakeDC/Auth.ApiKey', - 'CakeDC/Auth.RememberMe', - 'Form', - ], - 'authorize' => [ - 'CakeDC/Auth.Superuser', - 'CakeDC/Auth.SimpleRbac', - ], - ], - 'OAuth' => [ - 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'prefix' => null], - 'providers' => [ - 'facebook' => [ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.8', //bio field was deprecated on >= v2.8 - 'redirectUri' => Router::fullBaseUrl() . '/auth/facebook', - 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/facebook', - 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/facebook', - ] - ], - 'twitter' => [ - 'options' => [ - 'redirectUri' => Router::fullBaseUrl() . '/auth/twitter', - 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter', - 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/twitter', - ] - ], - 'linkedIn' => [ - 'className' => 'League\OAuth2\Client\Provider\LinkedIn', - 'options' => [ - 'redirectUri' => Router::fullBaseUrl() . '/auth/linkedIn', - 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/linkedIn', - 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/linkedIn', - ] - ], - 'instagram' => [ - 'className' => 'League\OAuth2\Client\Provider\Instagram', - 'options' => [ - 'redirectUri' => Router::fullBaseUrl() . '/auth/instagram', - 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/instagram', - 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/instagram', - ] - ], - 'google' => [ - 'className' => 'League\OAuth2\Client\Provider\Google', - 'options' => [ - 'userFields' => ['url', 'aboutMe'], - 'redirectUri' => Router::fullBaseUrl() . '/auth/google', - 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/google', - 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/google', - ] - ], - 'amazon' => [ - 'className' => 'Luchianenco\OAuth2\Client\Provider\Amazon', - 'options' => [ - 'redirectUri' => Router::fullBaseUrl() . '/auth/amazon', - 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/amazon', - 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/amazon', - ] - ], - ], - ] -]; - -return $config; diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index 500c19975..000000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - ./tests/TestCase - - - - - ./src - - - - - - - - - - - - diff --git a/src/Auth/DefaultTwoFactorAuthenticationChecker.php b/src/Auth/DefaultTwoFactorAuthenticationChecker.php deleted file mode 100644 index be0c1843f..000000000 --- a/src/Auth/DefaultTwoFactorAuthenticationChecker.php +++ /dev/null @@ -1,44 +0,0 @@ -isEnabled(); - } -} diff --git a/src/Auth/Exception/InvalidProviderException.php b/src/Auth/Exception/InvalidProviderException.php deleted file mode 100644 index d19eee654..000000000 --- a/src/Auth/Exception/InvalidProviderException.php +++ /dev/null @@ -1,31 +0,0 @@ - 'id', - 'username' => 'username', - 'full_name' => 'name', - 'first_name' => 'first_name', - 'last_name' => 'last_name', - 'email' => 'email', - 'avatar' => 'avatar', - 'gender' => 'gender', - 'link' => 'link', - 'bio' => 'bio', - 'locale' => 'locale', - 'validated' => 'validated' - ]; - - /** - * Constructor - * - * @param mixed $rawData raw data - * @param mixed $mapFields map fields - */ - public function __construct($rawData, $mapFields = null) - { - $this->_rawData = $rawData; - if (!is_null($mapFields)) { - $this->_mapFields = $mapFields; - } - $this->_mapFields = array_merge($this->_defaultMapFields, $this->_mapFields); - } - /** - * Invoke method - * - * @return mixed - */ - public function __invoke() - { - return $this->_map(); - } - - /** - * If email is present the user is validated - * - * @return bool - */ - protected function _validated() - { - $email = Hash::get($this->_rawData, $this->_mapFields['email']); - - return !empty($email); - } - - /** - * Maps raw data using mapFields - * - * @return mixed - */ - protected function _map() - { - $result = []; - collection($this->_mapFields)->each(function ($mappedField, $field) use (&$result) { - $value = Hash::get($this->_rawData, $mappedField); - $function = '_' . $field; - if (method_exists($this, $function)) { - $value = $this->{$function}(); - } - $result[$field] = $value; - }); - - $token = Hash::get($this->_rawData, 'token'); - if (empty($token) || !(is_array($token) || $token instanceof \League\OAuth2\Client\Token\AccessToken)) { - return false; - } - $result['credentials'] = [ - 'token' => is_array($token) ? Hash::get($token, 'accessToken') : $token->getToken(), - 'secret' => is_array($token) ? Hash::get($token, 'tokenSecret') : null, - 'expires' => is_array($token) ? Hash::get($token, 'expires') : $token->getExpires(), - ]; - $result['raw'] = $this->_rawData; - - return $result; - } -} diff --git a/src/Auth/Social/Mapper/Amazon.php b/src/Auth/Social/Mapper/Amazon.php deleted file mode 100644 index 20c532052..000000000 --- a/src/Auth/Social/Mapper/Amazon.php +++ /dev/null @@ -1,43 +0,0 @@ - 'user_id' - ]; - - /** - * @return string - */ - protected function _link() - { - return self::AMAZON_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['id']); - } -} diff --git a/src/Auth/Social/Mapper/Facebook.php b/src/Auth/Social/Mapper/Facebook.php deleted file mode 100644 index fbefa5010..000000000 --- a/src/Auth/Social/Mapper/Facebook.php +++ /dev/null @@ -1,52 +0,0 @@ - 'name', - ]; - - /** - * Get avatar url - * @return string - */ - protected function _avatar() - { - return self::FB_GRAPH_BASE_URL . Hash::get($this->_rawData, 'id') . '/picture?type=large'; - } - - /** - * @return string - */ - protected function _link() - { - return Hash::get($this->_rawData, 'link') ?: '#'; - } -} diff --git a/src/Auth/Social/Mapper/Google.php b/src/Auth/Social/Mapper/Google.php deleted file mode 100644 index b895d5361..000000000 --- a/src/Auth/Social/Mapper/Google.php +++ /dev/null @@ -1,43 +0,0 @@ - 'image.url', - 'full_name' => 'displayName', - 'email' => 'emails.0.value', - 'first_name' => 'name.givenName', - 'last_name' => 'name.familyName', - 'bio' => 'aboutMe', - 'link' => 'url' - ]; - - /** - * @return string - */ - protected function _link() - { - return Hash::get($this->_rawData, $this->_mapFields['link']) ?: '#'; - } -} diff --git a/src/Auth/Social/Mapper/Instagram.php b/src/Auth/Social/Mapper/Instagram.php deleted file mode 100644 index b6adecf1d..000000000 --- a/src/Auth/Social/Mapper/Instagram.php +++ /dev/null @@ -1,43 +0,0 @@ - 'full_name', - 'avatar' => 'profile_picture', - ]; - - /** - * @return string - */ - protected function _link() - { - return self::INSTAGRAM_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['username']); - } -} diff --git a/src/Auth/Social/Mapper/LinkedIn.php b/src/Auth/Social/Mapper/LinkedIn.php deleted file mode 100644 index cadda4b3c..000000000 --- a/src/Auth/Social/Mapper/LinkedIn.php +++ /dev/null @@ -1,28 +0,0 @@ - 'pictureUrl', - 'first_name' => 'firstName', - 'last_name' => 'lastName', - 'email' => 'emailAddress', - 'bio' => 'headline', - 'link' => 'publicProfileUrl' - ]; -} diff --git a/src/Auth/Social/Mapper/Pinterest.php b/src/Auth/Social/Mapper/Pinterest.php deleted file mode 100644 index d1b630b73..000000000 --- a/src/Auth/Social/Mapper/Pinterest.php +++ /dev/null @@ -1,24 +0,0 @@ - 'image.60x60.url', - 'link' => 'url', - ]; -} diff --git a/src/Auth/Social/Mapper/Tumblr.php b/src/Auth/Social/Mapper/Tumblr.php deleted file mode 100644 index 2f18418a8..000000000 --- a/src/Auth/Social/Mapper/Tumblr.php +++ /dev/null @@ -1,46 +0,0 @@ - 'uid', - 'username' => 'nickname', - 'full_name' => 'name', - 'first_name' => 'firstName', - 'last_name' => 'lastName', - 'email' => 'email', - 'avatar' => 'imageUrl', - 'bio' => 'extra.blogs.0.description', - 'validated' => 'validated', - 'link' => 'extra.blogs.0.url' - ]; - - /** - * @return string - */ - protected function _id() - { - return crc32($this->_rawData['nickname']); - } -} diff --git a/src/Auth/Social/Mapper/Twitter.php b/src/Auth/Social/Mapper/Twitter.php deleted file mode 100644 index 3dccfa45f..000000000 --- a/src/Auth/Social/Mapper/Twitter.php +++ /dev/null @@ -1,59 +0,0 @@ - 'uid', - 'username' => 'nickname', - 'full_name' => 'name', - 'first_name' => 'firstName', - 'last_name' => 'lastName', - 'email' => 'email', - 'avatar' => 'imageUrl', - 'bio' => 'description', - 'validated' => 'validated' - ]; - - /** - * @return string - */ - protected function _link() - { - return self::TWITTER_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['username']); - } - - /** - * @return string - */ - protected function _avatar() - { - return str_replace('normal', 'bigger', Hash::get($this->_rawData, $this->_mapFields['avatar'])); - } -} diff --git a/src/Auth/Social/Util/SocialUtils.php b/src/Auth/Social/Util/SocialUtils.php deleted file mode 100644 index 0ae12fbf1..000000000 --- a/src/Auth/Social/Util/SocialUtils.php +++ /dev/null @@ -1,35 +0,0 @@ -getShortName(); - } -} diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php deleted file mode 100755 index a5602c150..000000000 --- a/src/Auth/SocialAuthenticate.php +++ /dev/null @@ -1,488 +0,0 @@ -_isProviderEnabled($oauthConfig['providers']['twitter']); - //We unset twitter from providers to exclude from OAuth2 config - unset($oauthConfig['providers']['twitter']); - - $providers = []; - foreach ($oauthConfig['providers'] as $provider => $options) { - if ($this->_isProviderEnabled($options)) { - $providers[$provider] = $options; - } - } - $oauthConfig['providers'] = $providers; - Configure::write('OAuth2', $oauthConfig); - $config = $this->normalizeConfig(Hash::merge($config, $oauthConfig), $enabledNoOAuth2Provider); - parent::__construct($registry, $config); - } - - /** - * Normalizes providers' configuration. - * - * @param array $config Array of config to normalize. - * @param bool $enabledNoOAuth2Provider True when any noOAuth2 provider is enabled - * @return array - * @throws \Exception - */ - public function normalizeConfig(array $config, $enabledNoOAuth2Provider = false) - { - $config = Hash::merge((array)Configure::read('OAuth2'), $config); - - if (empty($config['providers']) && !$enabledNoOAuth2Provider) { - throw new MissingProviderConfigurationException(); - } - - if (!empty($config['providers'])) { - array_walk($config['providers'], [$this, '_normalizeConfig'], $config); - } - - return $config; - } - - /** - * Callback to loop through config values. - * - * @param array $config Configuration. - * @param string $alias Provider's alias (key) in configuration. - * @param array $parent Parent configuration. - * @return void - */ - protected function _normalizeConfig(&$config, $alias, $parent) - { - unset($parent['providers']); - - $defaults = [ - 'className' => null, - 'options' => [], - 'collaborators' => [], - 'mapFields' => [], - ] + $parent + $this->_defaultConfig; - - $config = array_intersect_key($config, $defaults); - $config += $defaults; - - array_walk($config, [$this, '_validateConfig']); - - foreach (['options', 'collaborators'] as $key) { - if (empty($parent[$key]) || empty($config[$key])) { - continue; - } - - $config[$key] = array_merge($parent[$key], $config[$key]); - } - } - - /** - * Validates the configuration. - * - * @param mixed $value Value. - * @param string $key Key. - * @return void - * @throws \CakeDC\Users\Auth\Exception\InvalidProviderException - * @throws \CakeDC\Users\Auth\Exception\InvalidSettingsException - */ - protected function _validateConfig(&$value, $key) - { - if ($key === 'className' && !class_exists($value)) { - throw new InvalidProviderException([$value]); - } elseif (!is_array($value) && in_array($key, ['options', 'collaborators'])) { - throw new InvalidSettingsException([$key]); - } - } - - /** - * Get the controller associated with the collection. - * - * @return \Cake\Controller\Controller Controller instance - */ - protected function _getController() - { - return $this->_registry->getController(); - } - - /** - * Returns when a provider has been enabled. - * - * @param array $options array of options by provider - * @return bool - */ - protected function _isProviderEnabled($options) - { - return !empty($options['options']['redirectUri']) && !empty($options['options']['clientId']) && - !empty($options['options']['clientSecret']); - } - - /** - * Get a user based on information in the request. - * - * @param \Cake\Http\ServerRequest $request Request object. - * @param \Cake\Http\Response $response Response object. - * @return bool - * @throws \RuntimeException If the `CakeDC/Users/OAuth2.newUser` event is missing or returns empty. - */ - public function authenticate(ServerRequest $request, Response $response) - { - return $this->getUser($request); - } - - /** - * Authenticates with OAuth2 provider by getting an access token and - * retrieving the authorized user's profile data. - * - * @param \Cake\Http\ServerRequest $request Request object. - * @return array|bool - */ - protected function _authenticate(ServerRequest $request) - { - if (!$this->_validate($request)) { - return false; - } - - $provider = $this->provider($request); - $code = $request->getQuery('code'); - - try { - $token = $provider->getAccessToken('authorization_code', compact('code')); - - return compact('token') + $provider->getResourceOwner($token)->toArray(); - } catch (\Exception $e) { - $message = sprintf( - "Error getting an access token / retrieving the authorized user's profile data. Error message: %s %s", - $e->getMessage(), - $e - ); - $this->log($message); - - return false; - } - } - - /** - * Validates OAuth2 request. - * - * @param \Cake\Http\ServerRequest $request Request object. - * @return bool - */ - protected function _validate(ServerRequest $request) - { - if (!array_key_exists('code', $request->getQueryParams()) || !$this->provider($request)) { - return false; - } - - $session = $request->getSession(); - $sessionKey = 'oauth2state'; - $state = $request->getQuery('state'); - - if ($this->getConfig('options.state') && - (!$state || $state !== $session->read($sessionKey))) { - $session->delete($sessionKey); - - return false; - } - - return true; - } - - /** - * Maps raw provider's user profile data to local user's data schema. - * - * @param array $data Raw user data. - * @return array - */ - protected function _map($data) - { - if (!$map = $this->getConfig('mapFields')) { - return $data; - } - - foreach ($map as $dst => $src) { - $data[$dst] = $data[$src]; - unset($data[$src]); - } - - return $data; - } - - /** - * Handles unauthenticated access attempts. Will automatically forward to the - * requested provider's authorization URL to let the user grant access to the - * application. - * - * @param \Cake\Http\ServerRequest $request Request object. - * @param \Cake\Http\Response $response Response object. - * @return \Cake\Http\Response|null - */ - public function unauthenticated(ServerRequest $request, Response $response) - { - $provider = $this->provider($request); - if (empty($provider) || !empty($request->getQuery('code'))) { - return null; - } - - if ($this->getConfig('options.state')) { - $request->getSession()->write('oauth2state', $provider->getState()); - } - - $response = $response->withLocation($provider->getAuthorizationUrl()); - - return $response; - } - - /** - * Returns the `$request`-ed provider. - * - * @param \Cake\Http\ServerRequest $request Current HTTP request. - * @return \League\Oauth2\Client\Provider\GenericProvider|false - */ - public function provider(ServerRequest $request) - { - if (!$alias = $request->getParam('provider')) { - return false; - } - - if (empty($this->_provider)) { - $this->_provider = $this->_getProvider($alias); - } - - return $this->_provider; - } - - /** - * Instantiates provider object. - * - * @param string $alias of the provider. - * @return \League\Oauth2\Client\Provider\GenericProvider - */ - protected function _getProvider($alias) - { - if (!$config = $this->getConfig('providers.' . $alias)) { - return false; - } - - $this->setConfig($config); - - if (is_object($config) && $config instanceof AbstractProvider) { - return $config; - } - - $class = $config['className']; - - return new $class($config['options'], $config['collaborators']); - } - - /** - * Find or create local user - * - * @param array $data data - * @return array|bool|mixed - * @throws MissingEmailException - */ - protected function _touch(array $data) - { - try { - if (empty($data['provider']) && !empty($this->_provider)) { - $data['provider'] = SocialUtils::getProvider($this->_provider); - } - $user = $this->_socialLogin($data); - } catch (UserNotActiveException $ex) { - $exception = $ex; - } catch (AccountNotActiveException $ex) { - $exception = $ex; - } catch (MissingEmailException $ex) { - $exception = $ex; - } - if (!empty($exception)) { - $args = ['exception' => $exception, 'rawData' => $data]; - $this->_getController()->dispatchEvent(UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, $args); - if (method_exists($this->_getController(), 'failedSocialLogin')) { - $this->_getController()->failedSocialLogin($exception, $data, true); - } - - return false; - } - - // If new SocialAccount was created $user is returned containing it - if ($user->get('social_accounts')) { - $this->_getController()->dispatchEvent(UsersAuthComponent::EVENT_AFTER_REGISTER, compact('user')); - } - - if (!empty($user->username)) { - $user = $this->_findUser($user->username); - } - - return $user; - } - - /** - * Get a user based on information in the request. - * - * @param \Cake\Http\ServerRequest $request Request object. - * @return mixed Either false or an array of user information - * @throws \RuntimeException If the `CakeDC/Users/OAuth2.newUser` event is missing or returns empty. - */ - public function getUser(ServerRequest $request) - { - $data = $request->getSession()->read(Configure::read('Users.Key.Session.social')); - $requestDataEmail = $request->getData('email'); - if (!empty($data) && empty($data['uid']) && (!empty($data['email']) || !empty($requestDataEmail))) { - if (!empty($requestDataEmail)) { - $data['email'] = $requestDataEmail; - } - $user = $data; - $request->getSession()->delete(Configure::read('Users.Key.Session.social')); - } else { - if (empty($data) && !$rawData = $this->_authenticate($request)) { - return false; - } - if (empty($rawData)) { - $rawData = $data; - } - - $provider = $this->_getProviderName($request); - try { - $user = $this->_mapUser($provider, $rawData); - if ($this->_getController()->components()->has('Auth')) { - $this->_getController()->Auth->setConfig('authError', false); - } - } catch (MissingProviderException $ex) { - $request->getSession()->delete(Configure::read('Users.Key.Session.social')); - throw $ex; - } - if ($user['provider'] === SocialAccountsTable::PROVIDER_TWITTER) { - $request->getSession()->write(Configure::read('Users.Key.Session.social'), $user); - } - } - - if (!$user || !$this->getConfig('userModel')) { - return false; - } - - if (!$result = $this->_touch($user)) { - return false; - } - - if ($request->getSession()->check(Configure::read('Users.Key.Session.social'))) { - $request->getSession()->delete(Configure::read('Users.Key.Session.social')); - } - $request->getSession()->write('Users.successSocialLogin', true); - - return $result; - } - - /** - * Get the provider name based on the request or on the provider set. - * - * @param \Cake\Http\ServerRequest $request Request object. - * @return mixed Either false or an array of user information - */ - protected function _getProviderName($request = null) - { - $provider = false; - if (!empty($request->getParam('provider'))) { - $provider = ucfirst($request->getParam('provider')); - } elseif (!is_null($this->_provider)) { - $provider = SocialUtils::getProvider($this->_provider); - } - - return $provider; - } - - /** - * Get the provider name based on the request or on the provider set. - * - * @param string $provider Provider name. - * @param array $data User data - * @throws MissingProviderException - * @return mixed Either false or an array of user information - */ - protected function _mapUser($provider, $data) - { - if (empty($provider)) { - throw new MissingProviderException(__d('CakeDC/Users', "Provider cannot be empty")); - } - $providerMapperClass = $this->getConfig('providers.' . strtolower($provider) . '.options.mapper') ?: "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; - $providerMapper = new $providerMapperClass($data); - $user = $providerMapper(); - $user['provider'] = $provider; - - return $user; - } - - /** - * @param mixed $data data - * @return mixed - */ - protected function _socialLogin($data) - { - $options = [ - 'use_email' => Configure::read('Users.Email.required'), - 'validate_email' => Configure::read('Users.Email.validate'), - 'token_expiration' => Configure::read('Users.Token.expiration') - ]; - - $userModel = Configure::read('Users.table'); - $User = TableRegistry::getTableLocator()->get($userModel); - $user = $User->socialLogin($data, $options); - - return $user; - } -} diff --git a/src/Auth/TwoFactorAuthenticationCheckerFactory.php b/src/Auth/TwoFactorAuthenticationCheckerFactory.php deleted file mode 100644 index 8287fdf1d..000000000 --- a/src/Auth/TwoFactorAuthenticationCheckerFactory.php +++ /dev/null @@ -1,39 +0,0 @@ -loadComponent('Security'); - if ($this->request->getParam('_csrfToken') === false) { - $this->loadComponent('Csrf'); - } - $this->loadComponent('CakeDC/Users.UsersAuth'); - } -} diff --git a/src/Controller/Component/GoogleAuthenticatorComponent.php b/src/Controller/Component/GoogleAuthenticatorComponent.php deleted file mode 100644 index 215e96853..000000000 --- a/src/Controller/Component/GoogleAuthenticatorComponent.php +++ /dev/null @@ -1,84 +0,0 @@ -tfa = new TwoFactorAuth( - Configure::read('Users.GoogleAuthenticator.issuer'), - Configure::read('Users.GoogleAuthenticator.digits'), - Configure::read('Users.GoogleAuthenticator.period'), - Configure::read('Users.GoogleAuthenticator.algorithm'), - Configure::read('Users.GoogleAuthenticator.qrcodeprovider'), - Configure::read('Users.GoogleAuthenticator.rngprovider') - ); - } - } - - /** - * createSecret - * @return string base32 shared secret stored in users table - */ - public function createSecret() - { - return $this->tfa->createSecret(); - } - - /** - * verifyCode - * Verifying tfa code with shared secret - * @param string $secret of the user - * @param string $code from verification form - * @return bool - */ - public function verifyCode($secret, $code) - { - return $this->tfa->verifyCode($secret, $code); - } - - /** - * getQRCodeImageAsDataUri - * @param string $issuer issuer - * @param string $secret secret - * @return string base64 string containing QR code for shared secret - */ - public function getQRCodeImageAsDataUri($issuer, $secret) - { - return $this->tfa->getQRCodeImageAsDataUri($issuer, $secret); - } -} diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php deleted file mode 100644 index 742d91b63..000000000 --- a/src/Controller/Component/RememberMeComponent.php +++ /dev/null @@ -1,159 +0,0 @@ -_cookieName = Configure::read('Users.RememberMe.Cookie.name'); - $this->_validateConfig(); - $this->setCookieOptions(); - $this->_attachEvents(); - } - - /** - * Validate component config - * - * @throws InvalidArgumentException - * @return void - */ - protected function _validateConfig() - { - if (mb_strlen(Security::getSalt(), '8bit') < 32) { - throw new InvalidArgumentException( - __d('CakeDC/Users', 'Invalid app salt, app salt must be at least 256 bits (32 bytes) long') - ); - } - } - - /** - * Attach the afterLogin and beforeLogount events - * - * @return void - */ - protected function _attachEvents() - { - $eventManager = $this->getController()->getEventManager(); - $eventManager->on(UsersAuthComponent::EVENT_AFTER_LOGIN, [], [$this, 'setLoginCookie']); - $eventManager->on(UsersAuthComponent::EVENT_BEFORE_LOGOUT, [], [$this, 'destroy']); - } - - /** - * Sets cookie configuration options - * - * @return void - */ - public function setCookieOptions() - { - $cookieConfig = Configure::read('Users.RememberMe.Cookie.Config'); - $this->Cookie->configKey($this->_cookieName, $cookieConfig); - } - - /** - * Sets the login cookie that handles the remember me feature - * - * @param Event $event event - * @return void - */ - public function setLoginCookie(Event $event) - { - $user['id'] = $this->Auth->user('id'); - if (empty($user)) { - return; - } - $user['user_agent'] = $this->getController()->getRequest()->getHeaderLine('User-Agent'); - if (!(bool)$this->getController()->getRequest()->getData(Configure::read('Users.Key.Data.rememberMe'))) { - return; - } - $this->Cookie->write($this->_cookieName, $user); - } - - /** - * Destroys the remember me cookie - * - * @param Event $event event - * @return void - */ - public function destroy(Event $event) - { - if ($this->Cookie->check($this->_cookieName)) { - $this->Cookie->delete($this->_cookieName); - } - } - - /** - * Reads the stored cookie and auto login the user if present - * - * @param Event $event event - * @return mixed - */ - public function beforeFilter(Event $event) - { - $user = $this->Auth->user(); - if (!empty($user) || - $this->getController()->getRequest()->is(['post', 'put']) || - $this->getController()->getRequest()->getParam('action') === 'logout' || - $this->getController()->getRequest()->getSession()->check(Configure::read('Users.Key.Session.social')) || - $this->getController()->getRequest()->getParam('provider')) { - return; - } - - $user = $this->Auth->identify(); - // No user no cookies - if (empty($user)) { - return; - } - $this->Auth->setUser($user); - $event = $this->getController()->dispatchEvent(UsersAuthComponent::EVENT_AFTER_COOKIE_LOGIN); - if (is_array($event->result)) { - return $this->getController()->redirect($event->result); - } - $url = $this->getController()->getRequest()->getRequestTarget(); - - return $this->getController()->redirect($url); - } -} diff --git a/src/Controller/Component/SetupComponent.php b/src/Controller/Component/SetupComponent.php deleted file mode 100644 index dc20cb060..000000000 --- a/src/Controller/Component/SetupComponent.php +++ /dev/null @@ -1,33 +0,0 @@ -getController()->loadComponent('CakeDC/Users.UsersAuth'); - list($plugin, $controller) = pluginSplit(Configure::read('Users.controller')); - if ($this->getController()->getRequest()->getParam('plugin', null) === $plugin && - $this->getController()->getRequest()->getParam('controller') === $controller - ) { - $this->getController()->Auth->allow(['login']); - } - } -} diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php deleted file mode 100644 index 92fa56e7d..000000000 --- a/src/Controller/Component/UsersAuthComponent.php +++ /dev/null @@ -1,247 +0,0 @@ -_validateConfig(); - $this->_initAuth(); - - if (Configure::read('Users.Social.login')) { - $this->_loadSocialLogin(); - } - if (Configure::read('Users.RememberMe.active')) { - $this->_loadRememberMe(); - } - - if ($this->getTwoFactorAuthenticationChecker()->isEnabled()) { - $this->_loadGoogleAuthenticator(); - } - - $this->_attachPermissionChecker(); - } - - /** - * Load GoogleAuthenticator object - * - * @return void - */ - protected function _loadGoogleAuthenticator() - { - $this->getController()->loadComponent('CakeDC/Users.GoogleAuthenticator'); - } - - /** - * Load Social Auth object - * - * @return void - */ - protected function _loadSocialLogin() - { - $this->getController()->Auth->setConfig('authenticate', [ - Configure::read('Users.Social.authenticator') - ], true); - } - - /** - * Load RememberMe component and Auth objects - * - * @return void - */ - protected function _loadRememberMe() - { - $this->getController()->loadComponent('CakeDC/Users.RememberMe'); - } - - /** - * Attach the isUrlAuthorized event to allow using the Auth authorize from the UserHelper - * - * @return void - */ - protected function _attachPermissionChecker() - { - EventManager::instance()->on(self::EVENT_IS_AUTHORIZED, [], [$this, 'isUrlAuthorized']); - } - - /** - * Initialize the AuthComponent and configure allowed actions - * - * @return void - */ - protected function _initAuth() - { - if (Configure::read('Users.auth')) { - //initialize Auth - $this->getController()->loadComponent('Auth', Configure::read('Auth')); - } - - list($plugin, $controller) = pluginSplit(Configure::read('Users.controller')); - if ($this->getController()->getRequest()->getParam('plugin', null) === $plugin && - $this->getController()->getRequest()->getParam('controller') === $controller - ) { - $this->getController()->Auth->allow([ - // LoginTrait - 'twitterLogin', - 'login', - 'socialEmail', - 'verify', - // RegisterTrait - 'register', - 'validateEmail', - // PasswordManagementTrait used in RegisterTrait - 'changePassword', - 'resetPassword', - 'requestResetPassword', - // UserValidationTrait used in PasswordManagementTrait - 'resendTokenValidation', - // Social - 'endpoint', - 'authenticated', - ]); - } - } - - /** - * Check if a given url is authorized - * - * @param Event $event event - * - * @return bool - */ - public function isUrlAuthorized(Event $event) - { - $url = Hash::get((array)$event->getData(), 'url'); - if (empty($url)) { - return false; - } - - if (is_array($url)) { - $requestUrl = Router::normalize(Router::reverse($url)); - $requestParams = Router::parseRequest(new ServerRequest($requestUrl)); - } else { - try { - //remove base from $url if exists - $normalizedUrl = Router::normalize($url); - $requestParams = Router::parseRequest(new ServerRequest($normalizedUrl)); - } catch (MissingRouteException $ex) { - //if it's a url pointing to our own app - if (substr($normalizedUrl, 0, 1) === '/') { - throw $ex; - } - - return true; - } - $requestUrl = $url; - } - // check if controller action is allowed - if ($this->_isActionAllowed($requestParams)) { - return true; - } - - // check we are logged in - $user = $this->getController()->Auth->user(); - if (empty($user)) { - return false; - } - - $request = new ServerRequest($requestUrl); - $request = $request->withAttribute('params', $requestParams); - - $isAuthorized = $this->getController()->Auth->isAuthorized(null, $request); - - return $isAuthorized; - } - - /** - * Validate if the passed configuration makes sense - * - * @throws BadConfigurationException - * @return void - */ - protected function _validateConfig() - { - if (!Configure::read('Users.Email.required') && Configure::read('Users.Email.validate')) { - $message = __d('CakeDC/Users', 'You can\'t enable email validation workflow if use_email is false'); - throw new BadConfigurationException($message); - } - } - - /** - * Check if the action is in allowedActions array for the controller - * Important, this function will check only for allowed actions in the current - * controller, creating a new instance and providing initialization for the Auth - * instance in another controller could lead to undesired side effects. - * - * @param array $requestParams request parameters - * @return bool - */ - protected function _isActionAllowed($requestParams = []) - { - if (empty($requestParams['action'])) { - return false; - } - if (!empty($requestParams['controller']) && $requestParams['controller'] !== $this->getController()->getName()) { - return false; - } - $action = strtolower($requestParams['action']); - if (in_array($action, array_map('strtolower', $this->getController()->Auth->allowedActions))) { - return true; - } - - return false; - } - - /** - * Get the configured two factory authentication - * - * @return \CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface - */ - protected function getTwoFactorAuthenticationChecker() - { - return (new TwoFactorAuthenticationCheckerFactory())->build(); - } -} diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php deleted file mode 100644 index b22507464..000000000 --- a/src/Controller/SocialAccountsController.php +++ /dev/null @@ -1,94 +0,0 @@ -Auth->allow(['validateAccount', 'resendValidation']); - } - - /** - * Validates social account - * - * @param string $provider provider - * @param string $reference reference - * @param string $token token - * @return Response - */ - public function validateAccount($provider, $reference, $token) - { - try { - $result = $this->SocialAccounts->validateAccount($provider, $reference, $token); - if ($result) { - $this->Flash->success(__d('CakeDC/Users', 'Account validated successfully')); - } else { - $this->Flash->error(__d('CakeDC/Users', 'Account could not be validated')); - } - } catch (RecordNotFoundException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Invalid token and/or social account')); - } catch (AccountAlreadyActiveException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Social Account already active')); - } catch (\Exception $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Social Account could not be validated')); - } - - return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - } - - /** - * Resends validation email if required - * - * @param string $provider provider - * @param string $reference reference - * @return mixed - * @throws AccountAlreadyActiveException - */ - public function resendValidation($provider, $reference) - { - try { - $result = $this->SocialAccounts->resendValidation($provider, $reference); - if ($result) { - $this->Flash->success(__d('CakeDC/Users', 'Email sent successfully')); - } else { - $this->Flash->error(__d('CakeDC/Users', 'Email could not be sent')); - } - } catch (RecordNotFoundException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Invalid account')); - } catch (AccountAlreadyActiveException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Social Account already active')); - } catch (\Exception $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Email could not be resent')); - } - - return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - } -} diff --git a/src/Controller/Traits/CustomUsersTableTrait.php b/src/Controller/Traits/CustomUsersTableTrait.php deleted file mode 100644 index f016f66de..000000000 --- a/src/Controller/Traits/CustomUsersTableTrait.php +++ /dev/null @@ -1,51 +0,0 @@ -_usersTable instanceof Table) { - return $this->_usersTable; - } - $this->_usersTable = TableRegistry::getTableLocator()->get(Configure::read('Users.table')); - - return $this->_usersTable; - } - - /** - * Set the users table - * - * @param Table $table table - * @return void - */ - public function setUsersTable(Table $table) - { - $this->_usersTable = $table; - } -} diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php deleted file mode 100644 index 9b10c960b..000000000 --- a/src/Controller/Traits/LinkSocialTrait.php +++ /dev/null @@ -1,237 +0,0 @@ -_getSocialProvider($alias); - - $temporaryCredentials = []; - if (ucfirst($alias) === SocialAccountsTable::PROVIDER_TWITTER) { - $temporaryCredentials = $provider->getTemporaryCredentials(); - $this->request->getSession()->write('temporary_credentials', $temporaryCredentials); - } - $authUrl = $provider->getAuthorizationUrl($temporaryCredentials); - if (empty($temporaryCredentials)) { - $this->request->session()->write('SocialLink.oauth2state', $provider->getState()); - } - - return $this->redirect($authUrl); - } - - /** - * Callback to get user information from provider - * - * @param string $alias of the provider. - * - * @throws \Cake\Http\Exception\NotFoundException Quando o provider informado nĆ£o existe - * @return \Cake\Http\Response Redirects to profile if okay or error - */ - public function callbackLinkSocial($alias = null) - { - $message = __d('CakeDC/Users', 'Could not associate account, please try again.'); - $provider = $this->_getSocialProvider($alias); - $error = false; - if (ucfirst($alias) === SocialAccountsTable::PROVIDER_TWITTER) { - $server = new Twitter([ - 'identifier' => Configure::read('OAuth.providers.twitter.options.clientId'), - 'secret' => Configure::read('OAuth.providers.twitter.options.clientSecret'), - 'callbackUri' => Configure::read('OAuth.providers.twitter.options.callbackLinkSocialUri'), - ]); - $oauthToken = $this->request->getQuery('oauth_token'); - $oauthVerifier = $this->request->getQuery('oauth_verifier'); - if (!empty($oauthToken) && !empty($oauthVerifier)) { - $temporaryCredentials = $this->request->getSession()->read('temporary_credentials'); - try { - $tokenCredentials = $server->getTokenCredentials($temporaryCredentials, $oauthToken, $oauthVerifier); - $data = (array)$server->getUserDetails($tokenCredentials); - $data['token'] = [ - 'accessToken' => $tokenCredentials->getIdentifier(), - 'tokenSecret' => $tokenCredentials->getSecret(), - ]; - } catch (\Exception $e) { - $error = $e; - } - } - } else { - if (!$this->_validateCallbackSocialLink()) { - $this->Flash->error($message); - - return $this->redirect(['action' => 'profile']); - } - $code = $this->request->getQuery('code'); - try { - $token = $provider->getAccessToken('authorization_code', compact('code')); - - $data = compact('token') + $provider->getResourceOwner($token)->toArray(); - } catch (\Exception $e) { - $error = $e; - } - } - - if (!empty($error) || empty($data)) { - $log = sprintf( - "Error getting an access token. Error message: %s %s", - $error->getMessage(), - $error - ); - $this->log($log); - - $this->Flash->error($message); - - return $this->redirect(['action' => 'profile']); - } - - try { - $data = $this->_mapSocialUser($alias, $data); - - $user = $this->getUsersTable()->get($this->Auth->user('id')); - - $this->getUsersTable()->linkSocialAccount($user, $data); - - if ($user->getErrors()) { - $this->Flash->error($message); - } else { - $this->Flash->success(__d('CakeDC/Users', 'Social account was associated.')); - } - } catch (\Exception $e) { - $log = sprintf( - "Error retrieving the authorized user's profile data. Error message: %s %s", - $e->getMessage(), - $e - ); - $this->log($log); - - $this->Flash->error($message); - } - - return $this->redirect(['action' => 'profile']); - } - - /** - * Get the provider name based on the request or on the provider set. - * - * @param string $alias of the provider. - * @param array $data User data. - * - * @throws MissingProviderException - * @return array - */ - protected function _mapSocialUser($alias, $data) - { - $alias = ucfirst($alias); - $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$alias"; - $providerMapper = new $providerMapperClass($data); - $user = $providerMapper(); - $user['provider'] = $alias; - - return $user; - } - - /** - * Instantiates provider object. - * - * @param string $alias of the provider. - * - * @throws \Cake\Http\Exception\NotFoundException - * @return \League\OAuth2\Client\Provider\AbstractProvider|\League\OAuth1\Client\Server\Twitter - */ - protected function _getSocialProvider($alias) - { - $config = Configure::read('OAuth.providers.' . $alias); - if (!$config || !isset($config['options'], $config['options']['callbackLinkSocialUri'])) { - throw new NotFoundException; - } - - if (!isset($config['options']['clientId'], $config['options']['clientSecret'])) { - throw new NotFoundException; - } - - return $this->_createSocialProvider($config, ucfirst($alias)); - } - - /** - * Instantiates provider object. - * - * @param array $config for social provider. - * @param string $alias provider alias - * - * @throws \Cake\Http\Exception\NotFoundException - * @return \League\OAuth2\Client\Provider\AbstractProvider|\League\OAuth1\Client\Server\Twitter - */ - protected function _createSocialProvider($config, $alias = null) - { - if ($alias === SocialAccountsTable::PROVIDER_TWITTER) { - $server = new Twitter([ - 'identifier' => Configure::read('OAuth.providers.twitter.options.clientId'), - 'secret' => Configure::read('OAuth.providers.twitter.options.clientSecret'), - 'callback_uri' => Configure::read('OAuth.providers.twitter.options.callbackLinkSocialUri'), - ]); - - return $server; - } - $class = $config['className']; - $redirectUri = $config['options']['callbackLinkSocialUri']; - - unset($config['options']['callbackLinkSocialUri'], $config['options']['linkSocialUri']); - - $config['options']['redirectUri'] = $redirectUri; - - return new $class($config['options'], []); - } - - /** - * Validates OAuth2 request. - * - * @return bool - */ - protected function _validateCallbackSocialLink() - { - $queryParams = $this->request->getQueryParams(); - - if (isset($queryParams['error']) && !empty($queryParams['error'])) { - $this->log('Got error in _validateCallbackSocialLink: ' . htmlspecialchars($queryParams['error'], ENT_QUOTES, 'UTF-8')); - - return false; - } - - if (!array_key_exists('code', $queryParams)) { - return false; - } - - $sessionKey = 'SocialLink.oauth2state'; - $oauth2state = $this->request->session()->read($sessionKey); - $this->request->session()->delete($sessionKey); - $state = $queryParams['state']; - - return $oauth2state === $state; - } -} diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 0a602c85d..d33a9c3c6 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -272,6 +272,7 @@ public function verify() $verificationCode = $this->request->getData('code'); $user = $this->request->getSession()->read('temporarySession'); $entity = $this->getUsersTable()->get($user['id']); + $userRememberMe = $this->request->getSession()->read('Users.hasRememberMe'); if (!empty($entity['secret'])) { $codeVerified = $this->GoogleAuthenticator->verifyCode($entity['secret'], $verificationCode); @@ -289,12 +290,9 @@ public function verify() $user['secret_verified'] = true; } - // Push the remember me value to post data - // for after login event auth - $hasRememberMe = $this->request->getSession()->read('hasRememberMe'); - if ($hasRememberMe) { - $this->request->data(Configure::read('Users.RememberMe.Cookie.name'), $hasRememberMe); - $this->request->getSession()->delete('hasRememberMe'); + if ($userRememberMe) { + $this->request->data(Configure::read('Users.RememberMe.Cookie.name'), $userRememberMe); + $this->request->getSession()->delete('Users.hasRememberMe'); } $this->request->getSession()->delete('temporarySession'); @@ -348,10 +346,8 @@ protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthen // until the GA verification is checked $this->request->getSession()->write('temporarySession', $user); - // store the remember me value from login into session temporarily - // to pass the value to verify action if (Configure::read('Users.RememberMe.active')) { - $this->request->getSession()->write('hasRememberMe', $this->request->getData(Configure::read('Users.RememberMe.Cookie.name'))); + $this->request->getSession()->write('Users.hasRememberMe', $this->request->getData(Configure::read('Users.RememberMe.Cookie.name'))); } $url = Configure::read('GoogleAuthenticator.verifyAction'); diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php deleted file mode 100644 index ddd07b9c8..000000000 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ /dev/null @@ -1,180 +0,0 @@ -getUsersTable()->newEntity(); - $id = $this->Auth->user('id'); - if (!empty($id)) { - $user->id = $this->Auth->user('id'); - $validatePassword = true; - //@todo add to the documentation: list of routes used - $redirect = Configure::read('Users.Profile.route'); - } else { - $user->id = $this->request->getSession()->read(Configure::read('Users.Key.Session.resetPasswordUserId')); - $validatePassword = false; - if (!$user->id) { - $this->Flash->error(__d('CakeDC/Users', 'User was not found')); - $this->redirect($this->Auth->getConfig('loginAction')); - - return; - } - //@todo add to the documentation: list of routes used - $redirect = $this->Auth->getConfig('loginAction'); - } - $this->set('validatePassword', $validatePassword); - if ($this->request->is('post')) { - try { - $validator = $this->getUsersTable()->validationPasswordConfirm(new Validator()); - if (!empty($id)) { - $validator = $this->getUsersTable()->validationCurrentPassword($validator); - } - $user = $this->getUsersTable()->patchEntity( - $user, - $this->request->getData(), - ['validate' => $validator] - ); - if ($user->getErrors()) { - $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); - } else { - $result = $this->getUsersTable()->changePassword($user); - if ($result) { - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_CHANGE_PASSWORD, ['user' => $result]); - if (!empty($event) && is_array($event->result)) { - return $this->redirect($event->result); - } - $this->Flash->success(__d('CakeDC/Users', 'Password has been changed successfully')); - - return $this->redirect($redirect); - } else { - $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); - } - } - } catch (UserNotFoundException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'User was not found')); - } catch (WrongPasswordException $wpe) { - $this->Flash->error($wpe->getMessage()); - } catch (Exception $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); - $this->log($exception->getMessage()); - } - } - $this->set(compact('user')); - $this->set('_serialize', ['user']); - } - - /** - * Reset password - * - * @param null $token token data. - * @return void - */ - public function resetPassword($token = null) - { - $this->validate('password', $token); - } - - /** - * Reset password - * - * @return void|\Cake\Http\Response - */ - public function requestResetPassword() - { - $this->set('user', $this->getUsersTable()->newEntity()); - $this->set('_serialize', ['user']); - if (!$this->request->is('post')) { - return; - } - - $reference = $this->request->getData('reference'); - try { - $resetUser = $this->getUsersTable()->resetToken($reference, [ - 'expiration' => Configure::read('Users.Token.expiration'), - 'checkActive' => false, - 'sendEmail' => true, - 'ensureActive' => Configure::read('Users.Registration.ensureActive'), - 'type' => 'password' - ]); - if ($resetUser) { - $msg = __d('CakeDC/Users', 'Please check your email to continue with password reset process'); - $this->Flash->success($msg); - } else { - $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); - $this->Flash->error($msg); - } - - return $this->redirect(['action' => 'login']); - } catch (UserNotFoundException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'User {0} was not found', $reference)); - } catch (UserNotActiveException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'The user is not active')); - } catch (Exception $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); - $this->log($exception->getMessage()); - } - } - - /** - * resetGoogleAuthenticator - * - * Resets Google Authenticator token by setting secret_verified - * to false. - * - * @param mixed $id of the user record. - * @return mixed. - */ - public function resetGoogleAuthenticator($id = null) - { - if ($this->request->is('post')) { - try { - $query = $this->getUsersTable()->query(); - $query->update() - ->set(['secret_verified' => false, 'secret' => null]) - ->where(['id' => $id]); - $query->execute(); - - $message = __d('CakeDC/Users', 'Google Authenticator token was successfully reset'); - $this->Flash->success($message, 'default'); - } catch (\Exception $e) { - $message = $e->getMessage(); - $this->Flash->error($message, 'default'); - } - } - - return $this->redirect($this->request->referer()); - } -} diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php deleted file mode 100644 index db61724d3..000000000 --- a/src/Controller/Traits/ProfileTrait.php +++ /dev/null @@ -1,61 +0,0 @@ -Auth->user('id'); - $isCurrentUser = false; - if (!Configure::read('Users.Profile.viewOthers') || empty($id)) { - $id = $loggedUserId; - } - try { - $appContain = (array)Configure::read('Auth.authenticate.' . AuthComponent::ALL . '.contain'); - $socialContain = Configure::read('Users.Social.login') ? ['SocialAccounts']: []; - $user = $this->getUsersTable()->get($id, [ - 'contain' => array_merge((array)$appContain, (array)$socialContain) - ]); - $this->set('avatarPlaceholder', Configure::read('Users.Avatar.placeholder')); - if ($user->id === $loggedUserId) { - $isCurrentUser = true; - } - } catch (RecordNotFoundException $ex) { - $this->Flash->error(__d('CakeDC/Users', 'User was not found')); - - return $this->redirect($this->request->referer()); - } catch (InvalidPrimaryKeyException $ex) { - $this->Flash->error(__d('CakeDC/Users', 'Not authorized, please login first')); - - return $this->redirect($this->request->referer()); - } - $this->set(compact('user', 'isCurrentUser')); - $this->set('_serialize', ['user', 'isCurrentUser']); - } -} diff --git a/src/Controller/Traits/ReCaptchaTrait.php b/src/Controller/Traits/ReCaptchaTrait.php deleted file mode 100644 index d35773e77..000000000 --- a/src/Controller/Traits/ReCaptchaTrait.php +++ /dev/null @@ -1,57 +0,0 @@ -_getReCaptchaInstance(); - if (!empty($recaptcha)) { - $response = $recaptcha->verify($recaptchaResponse, $clientIp); - - return $response->isSuccess(); - } - - return false; - } - - /** - * Create reCaptcha instance if enabled in configuration - * - * @return \ReCaptcha\ReCaptcha - */ - protected function _getReCaptchaInstance() - { - $reCaptchaSecret = Configure::read('Users.reCaptcha.secret'); - if (!empty($reCaptchaSecret)) { - return new \ReCaptcha\ReCaptcha($reCaptchaSecret); - } - - return null; - } -} diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php deleted file mode 100644 index fc29ef602..000000000 --- a/src/Controller/Traits/RegisterTrait.php +++ /dev/null @@ -1,155 +0,0 @@ -Auth->user('id'); - if (!empty($userId) && !Configure::read('Users.Registration.allowLoggedIn')) { - $this->Flash->error(__d('CakeDC/Users', 'You must log out to register a new user account')); - - return $this->redirect(Configure::read('Users.Profile.route')); - } - - $usersTable = $this->getUsersTable(); - $user = $usersTable->newEntity(); - $validateEmail = (bool)Configure::read('Users.Email.validate'); - $useTos = (bool)Configure::read('Users.Tos.required'); - $tokenExpiration = Configure::read('Users.Token.expiration'); - $options = [ - 'token_expiration' => $tokenExpiration, - 'validate_email' => $validateEmail, - 'use_tos' => $useTos - ]; - $requestData = $this->request->getData(); - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_REGISTER, [ - 'usersTable' => $usersTable, - 'options' => $options, - 'userEntity' => $user, - ]); - - if ($event->result instanceof EntityInterface) { - $data = $event->result->toArray(); - $data['password'] = $requestData['password']; //since password is a hidden property - if ($userSaved = $usersTable->register($user, $data, $options)) { - return $this->_afterRegister($userSaved); - } else { - $this->set(compact('user')); - $this->Flash->error(__d('CakeDC/Users', 'The user could not be saved')); - - return; - } - } - if ($event->isStopped()) { - return $this->redirect($event->result); - } - - $this->set(compact('user')); - $this->set('_serialize', ['user']); - - if (!$this->request->is('post')) { - return; - } - - if (!$this->_validateRegisterPost()) { - $this->Flash->error(__d('CakeDC/Users', 'Invalid reCaptcha')); - - return; - } - - $userSaved = $usersTable->register($user, $requestData, $options); - if (!$userSaved) { - $this->Flash->error(__d('CakeDC/Users', 'The user could not be saved')); - - return; - } - - return $this->_afterRegister($userSaved); - } - - /** - * Check the POST and validate it for registration, for now we check the reCaptcha - * - * @return bool - */ - protected function _validateRegisterPost() - { - if (!Configure::read('Users.reCaptcha.registration')) { - return true; - } - - return $this->validateReCaptcha( - $this->request->getData('g-recaptcha-response'), - $this->request->clientIp() - ); - } - - /** - * Prepare flash messages after registration, and dispatch afterRegister event - * - * @param EntityInterface $userSaved User entity saved - * @return Response - */ - protected function _afterRegister(EntityInterface $userSaved) - { - $validateEmail = (bool)Configure::read('Users.Email.validate'); - $message = __d('CakeDC/Users', 'You have registered successfully, please log in'); - if ($validateEmail) { - $message = __d('CakeDC/Users', 'Please validate your account before log in'); - } - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_REGISTER, [ - 'user' => $userSaved - ]); - if ($event->result instanceof Response) { - return $event->result; - } - $this->Flash->success($message); - - return $this->redirect(['action' => 'login']); - } - - /** - * Validate an email - * - * @param string $token token - * @return void - */ - public function validateEmail($token = null) - { - $this->validate('email', $token); - } -} diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php deleted file mode 100644 index 4f2480a0a..000000000 --- a/src/Controller/Traits/SimpleCrudTrait.php +++ /dev/null @@ -1,138 +0,0 @@ -loadModel(); - $tableAlias = $table->getAlias(); - $this->set($tableAlias, $this->paginate($table)); - $this->set('tableAlias', $tableAlias); - $this->set('_serialize', [$tableAlias, 'tableAlias']); - } - - /** - * View method - * - * @param string|null $id User id. - * @return void - * @throws NotFoundException When record not found. - */ - public function view($id = null) - { - $table = $this->loadModel(); - $tableAlias = $table->getAlias(); - $entity = $table->get($id, [ - 'contain' => [] - ]); - $this->set($tableAlias, $entity); - $this->set('tableAlias', $tableAlias); - $this->set('_serialize', [$tableAlias, 'tableAlias']); - } - - /** - * Add method - * - * @return mixed Redirects on successful add, renders view otherwise. - */ - public function add() - { - $table = $this->loadModel(); - $tableAlias = $table->getAlias(); - $entity = $table->newEntity(); - $this->set($tableAlias, $entity); - $this->set('tableAlias', $tableAlias); - $this->set('_serialize', [$tableAlias, 'tableAlias']); - if (!$this->request->is('post')) { - return; - } - $entity = $table->patchEntity($entity, $this->request->getData()); - $singular = Inflector::singularize(Inflector::humanize($tableAlias)); - if ($table->save($entity)) { - $this->Flash->success(__d('CakeDC/Users', 'The {0} has been saved', $singular)); - - return $this->redirect(['action' => 'index']); - } - $this->Flash->error(__d('CakeDC/Users', 'The {0} could not be saved', $singular)); - } - - /** - * Edit method - * - * @param string|null $id User id. - * @return mixed Redirects on successful edit, renders view otherwise. - * @throws NotFoundException When record not found. - */ - public function edit($id = null) - { - $table = $this->loadModel(); - $tableAlias = $table->getAlias(); - $entity = $table->get($id, [ - 'contain' => [] - ]); - $this->set($tableAlias, $entity); - $this->set('tableAlias', $tableAlias); - $this->set('_serialize', [$tableAlias, 'tableAlias']); - if (!$this->request->is(['patch', 'post', 'put'])) { - return; - } - $entity = $table->patchEntity($entity, $this->request->getData()); - $singular = Inflector::singularize(Inflector::humanize($tableAlias)); - if ($table->save($entity)) { - $this->Flash->success(__d('CakeDC/Users', 'The {0} has been saved', $singular)); - - return $this->redirect(['action' => 'index']); - } - $this->Flash->error(__d('CakeDC/Users', 'The {0} could not be saved', $singular)); - } - - /** - * Delete method - * - * @param string|null $id User id. - * @return Response Redirects to index. - * @throws NotFoundException When record not found. - */ - public function delete($id = null) - { - $this->request->allowMethod(['post', 'delete']); - $table = $this->loadModel(); - $tableAlias = $table->getAlias(); - $entity = $table->get($id, [ - 'contain' => [] - ]); - $singular = Inflector::singularize(Inflector::humanize($tableAlias)); - if ($table->delete($entity)) { - $this->Flash->success(__d('CakeDC/Users', 'The {0} has been deleted', $singular)); - } else { - $this->Flash->error(__d('CakeDC/Users', 'The {0} could not be deleted', $singular)); - } - - return $this->redirect(['action' => 'index']); - } -} diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php deleted file mode 100644 index f019f9e1d..000000000 --- a/src/Controller/Traits/SocialTrait.php +++ /dev/null @@ -1,49 +0,0 @@ -request->getSession()->check(Configure::read('Users.Key.Session.social'))) { - throw new NotFoundException(); - } - $this->request->getSession()->delete('Flash.auth'); - - if ($this->request->is('post')) { - $validPost = $this->_validateRegisterPost(); - if (!$validPost) { - $this->Flash->error(__d('CakeDC/Users', 'The reCaptcha could not be validated')); - - return; - } - $user = $this->Auth->identify(); - - return $this->_afterIdentifyUser($user, true); - } - } -} diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php deleted file mode 100644 index 1b920f23f..000000000 --- a/src/Controller/Traits/UserValidationTrait.php +++ /dev/null @@ -1,123 +0,0 @@ -getUsersTable()->validate($token, 'activateUser'); - if ($result) { - $this->Flash->success(__d('CakeDC/Users', 'User account validated successfully')); - } else { - $this->Flash->error(__d('CakeDC/Users', 'User account could not be validated')); - } - } catch (UserAlreadyActiveException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'User already active')); - } - break; - case 'password': - $result = $this->getUsersTable()->validate($token); - if (!empty($result)) { - $this->Flash->success(__d('CakeDC/Users', 'Reset password token was validated successfully')); - $this->request->getSession()->write( - Configure::read('Users.Key.Session.resetPasswordUserId'), - $result->id - ); - - return $this->redirect(['action' => 'changePassword']); - } else { - $this->Flash->error(__d('CakeDC/Users', 'Reset password token could not be validated')); - } - break; - default: - $this->Flash->error(__d('CakeDC/Users', 'Invalid validation type')); - } - } catch (UserNotFoundException $ex) { - $this->Flash->error(__d('CakeDC/Users', 'Invalid token or user account already validated')); - } catch (TokenExpiredException $ex) { - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_ON_EXPIRED_TOKEN, ['type' => $type]); - if (!empty($event) && is_array($event->result)) { - return $this->redirect($event->result); - } - $this->Flash->error(__d('CakeDC/Users', 'Token already expired')); - } - - return $this->redirect(['action' => 'login']); - } - - /** - * Resend Token validation - * - * @return mixed - */ - public function resendTokenValidation() - { - $this->set('user', $this->getUsersTable()->newEntity()); - $this->set('_serialize', ['user']); - if (!$this->request->is('post')) { - return; - } - $reference = $this->request->getData('reference'); - try { - if ($this->getUsersTable()->resetToken($reference, [ - 'expiration' => Configure::read('Users.Token.expiration'), - 'checkActive' => true, - 'sendEmail' => true, - 'type' => 'email' - ])) { - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_RESEND_TOKEN_VALIDATION); - if (!empty($event) && is_array($event->result)) { - return $this->redirect($event->result); - } - $this->Flash->success(__d( - 'CakeDC/Users', - 'Token has been reset successfully. Please check your email.' - )); - } else { - $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); - } - - return $this->redirect(['action' => 'login']); - } catch (UserNotFoundException $ex) { - $this->Flash->error(__d('CakeDC/Users', 'User {0} was not found', $reference)); - } catch (UserAlreadyActiveException $ex) { - $this->Flash->error(__d('CakeDC/Users', 'User {0} is already active', $reference)); - } catch (Exception $ex) { - $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); - } - } -} diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php deleted file mode 100644 index b86bd0940..000000000 --- a/src/Controller/UsersController.php +++ /dev/null @@ -1,41 +0,0 @@ - -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2017-10-14 23:45+0000\n" -"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" -"Last-Translator: NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" - -#: Auth/SocialAuthenticate.php:456 -msgid "Provider cannot be empty" -msgstr "" - -#: Controller/SocialAccountsController.php:52 -msgid "Account validated successfully" -msgstr "" - -#: Controller/SocialAccountsController.php:54 -msgid "Account could not be validated" -msgstr "" - -#: Controller/SocialAccountsController.php:57 -msgid "Invalid token and/or social account" -msgstr "" - -#: Controller/SocialAccountsController.php:59;87 -msgid "Social Account already active" -msgstr "" - -#: Controller/SocialAccountsController.php:61 -msgid "Social Account could not be validated" -msgstr "" - -#: Controller/SocialAccountsController.php:80 -msgid "Email sent successfully" -msgstr "" - -#: Controller/SocialAccountsController.php:82 -msgid "Email could not be sent" -msgstr "" - -#: Controller/SocialAccountsController.php:85 -msgid "Invalid account" -msgstr "" - -#: Controller/SocialAccountsController.php:89 -msgid "Email could not be resent" -msgstr "" - -#: Controller/Component/RememberMeComponent.php:68 -msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" -msgstr "" - -#: Controller/Component/UsersAuthComponent.php:204 -msgid "You can't enable email validation workflow if use_email is false" -msgstr "" - -#: Controller/Traits/LinkSocialTrait.php:54 -msgid "Could not associate account, please try again." -msgstr "" - -#: Controller/Traits/LinkSocialTrait.php:77 -msgid "Social account was associated." -msgstr "" - -#: Controller/Traits/LoginTrait.php:104 -msgid "Issues trying to log in with your social account" -msgstr "" - -#: Controller/Traits/LoginTrait.php:109 -#: Template/Users/social_email.ctp:16 -msgid "Please enter your email" -msgstr "" - -#: Controller/Traits/LoginTrait.php:120 -msgid "Your user has not been validated yet. Please check your inbox for instructions" -msgstr "" - -#: Controller/Traits/LoginTrait.php:125 -msgid "Your social account has not been validated yet. Please check your inbox for instructions" -msgstr "" - -#: Controller/Traits/LoginTrait.php:180 -#: Controller/Traits/RegisterTrait.php:82 -msgid "Invalid reCaptcha" -msgstr "" - -#: Controller/Traits/LoginTrait.php:191 -msgid "You are already logged in" -msgstr "" - -#: Controller/Traits/LoginTrait.php:212 -msgid "Please enable Google Authenticator first." -msgstr "" - -#: Controller/Traits/LoginTrait.php:287 -msgid "Verification code is invalid. Try again" -msgstr "" - -#: Controller/Traits/LoginTrait.php:340 -msgid "Username or password is incorrect" -msgstr "" - -#: Controller/Traits/LoginTrait.php:363 -msgid "You've successfully logged out" -msgstr "" - -#: Controller/Traits/PasswordManagementTrait.php:49;82 -#: Controller/Traits/ProfileTrait.php:50 -msgid "User was not found" -msgstr "" - -#: Controller/Traits/PasswordManagementTrait.php:70;78;86 -msgid "Password could not be changed" -msgstr "" - -#: Controller/Traits/PasswordManagementTrait.php:74 -msgid "Password has been changed successfully" -msgstr "" - -#: Controller/Traits/PasswordManagementTrait.php:84 -msgid "{0}" -msgstr "" - -#: Controller/Traits/PasswordManagementTrait.php:127 -msgid "Please check your email to continue with password reset process" -msgstr "" - -#: Controller/Traits/PasswordManagementTrait.php:130 -#: Shell/UsersShell.php:247 -msgid "The password token could not be generated. Please try again" -msgstr "" - -#: Controller/Traits/PasswordManagementTrait.php:136 -#: Controller/Traits/UserValidationTrait.php:107 -msgid "User {0} was not found" -msgstr "" - -#: Controller/Traits/PasswordManagementTrait.php:138 -msgid "The user is not active" -msgstr "" - -#: Controller/Traits/PasswordManagementTrait.php:140 -#: Controller/Traits/UserValidationTrait.php:102;111 -msgid "Token could not be reset" -msgstr "" - -#: Controller/Traits/PasswordManagementTrait.php:164 -msgid "Google Authenticator token was successfully reset" -msgstr "" - -#: Controller/Traits/ProfileTrait.php:54 -msgid "Not authorized, please login first" -msgstr "" - -#: Controller/Traits/RegisterTrait.php:43 -msgid "You must log out to register a new user account" -msgstr "" - -#: Controller/Traits/RegisterTrait.php:89 -msgid "The user could not be saved" -msgstr "" - -#: Controller/Traits/RegisterTrait.php:123 -msgid "You have registered successfully, please log in" -msgstr "" - -#: Controller/Traits/RegisterTrait.php:125 -msgid "Please validate your account before log in" -msgstr "" - -#: Controller/Traits/SimpleCrudTrait.php:77;107 -msgid "The {0} has been saved" -msgstr "" - -#: Controller/Traits/SimpleCrudTrait.php:81;111 -msgid "The {0} could not be saved" -msgstr "" - -#: Controller/Traits/SimpleCrudTrait.php:131 -msgid "The {0} has been deleted" -msgstr "" - -#: Controller/Traits/SimpleCrudTrait.php:133 -msgid "The {0} could not be deleted" -msgstr "" - -#: Controller/Traits/SocialTrait.php:40 -msgid "The reCaptcha could not be validated" -msgstr "" - -#: Controller/Traits/UserValidationTrait.php:43 -msgid "User account validated successfully" -msgstr "" - -#: Controller/Traits/UserValidationTrait.php:45 -msgid "User account could not be validated" -msgstr "" - -#: Controller/Traits/UserValidationTrait.php:48 -msgid "User already active" -msgstr "" - -#: Controller/Traits/UserValidationTrait.php:54 -msgid "Reset password token was validated successfully" -msgstr "" - -#: Controller/Traits/UserValidationTrait.php:62 -msgid "Reset password token could not be validated" -msgstr "" - -#: Controller/Traits/UserValidationTrait.php:66 -msgid "Invalid validation type" -msgstr "" - -#: Controller/Traits/UserValidationTrait.php:69 -msgid "Invalid token or user account already validated" -msgstr "" - -#: Controller/Traits/UserValidationTrait.php:71 -msgid "Token already expired" -msgstr "" - -#: Controller/Traits/UserValidationTrait.php:97 -msgid "Token has been reset successfully. Please check your email." -msgstr "" - -#: Controller/Traits/UserValidationTrait.php:109 -msgid "User {0} is already active" -msgstr "" - -#: Mailer/UsersMailer.php:34 -msgid "Your account validation link" -msgstr "" - -#: Mailer/UsersMailer.php:52 -msgid "{0}Your reset password link" -msgstr "" - -#: Mailer/UsersMailer.php:75 -msgid "{0}Your social account validation link" -msgstr "" - -#: Model/Behavior/AuthFinderBehavior.php:49 -msgid "Missing 'username' in options data" -msgstr "" - -#: Model/Behavior/LinkSocialBehavior.php:53 -msgid "Social account already associated to another user" -msgstr "" - -#: Model/Behavior/PasswordBehavior.php:45 -msgid "Reference cannot be null" -msgstr "" - -#: Model/Behavior/PasswordBehavior.php:50 -msgid "Token expiration cannot be empty" -msgstr "" - -#: Model/Behavior/PasswordBehavior.php:56;117 -msgid "User not found" -msgstr "" - -#: Model/Behavior/PasswordBehavior.php:60 -#: Model/Behavior/RegisterBehavior.php:112;205 -msgid "User account already validated" -msgstr "" - -#: Model/Behavior/PasswordBehavior.php:67 -msgid "User not active" -msgstr "" - -#: Model/Behavior/PasswordBehavior.php:122 -msgid "The current password does not match" -msgstr "" - -#: Model/Behavior/PasswordBehavior.php:125 -msgid "You cannot use the current password as the new one" -msgstr "" - -#: Model/Behavior/RegisterBehavior.php:90 -msgid "User not found for the given token and email." -msgstr "" - -#: Model/Behavior/RegisterBehavior.php:93 -msgid "Token has already expired user with no token" -msgstr "" - -#: Model/Behavior/SocialAccountBehavior.php:103;130 -msgid "Account already validated" -msgstr "" - -#: Model/Behavior/SocialAccountBehavior.php:106;133 -msgid "Account not found for the given token and email." -msgstr "" - -#: Model/Behavior/SocialBehavior.php:82 -msgid "Unable to login user with reference {0}" -msgstr "" - -#: Model/Behavior/SocialBehavior.php:121 -msgid "Email not present" -msgstr "" - -#: Model/Table/UsersTable.php:81 -msgid "Your password does not match your confirm password. Please try again" -msgstr "" - -#: Model/Table/UsersTable.php:173 -msgid "Username already exists" -msgstr "" - -#: Model/Table/UsersTable.php:179 -msgid "Email already exists" -msgstr "" - -#: Shell/UsersShell.php:58 -msgid "Utilities for CakeDC Users Plugin" -msgstr "" - -#: Shell/UsersShell.php:60 -msgid "Activate an specific user" -msgstr "" - -#: Shell/UsersShell.php:63 -msgid "Add a new superadmin user for testing purposes" -msgstr "" - -#: Shell/UsersShell.php:66 -msgid "Add a new user" -msgstr "" - -#: Shell/UsersShell.php:69 -msgid "Change the role for an specific user" -msgstr "" - -#: Shell/UsersShell.php:72 -msgid "Deactivate an specific user" -msgstr "" - -#: Shell/UsersShell.php:75 -msgid "Delete an specific user" -msgstr "" - -#: Shell/UsersShell.php:78 -msgid "Reset the password via email" -msgstr "" - -#: Shell/UsersShell.php:81 -msgid "Reset the password for all users" -msgstr "" - -#: Shell/UsersShell.php:84 -msgid "Reset the password for an specific user" -msgstr "" - -#: Shell/UsersShell.php:133;159 -msgid "Please enter a password." -msgstr "" - -#: Shell/UsersShell.php:137 -msgid "Password changed for all users" -msgstr "" - -#: Shell/UsersShell.php:138;166 -msgid "New password: {0}" -msgstr "" - -#: Shell/UsersShell.php:156;184;262;359 -msgid "Please enter a username." -msgstr "" - -#: Shell/UsersShell.php:165 -msgid "Password changed for user: {0}" -msgstr "" - -#: Shell/UsersShell.php:187 -msgid "Please enter a role." -msgstr "" - -#: Shell/UsersShell.php:193 -msgid "Role changed for user: {0}" -msgstr "" - -#: Shell/UsersShell.php:194 -msgid "New role: {0}" -msgstr "" - -#: Shell/UsersShell.php:209 -msgid "User was activated: {0}" -msgstr "" - -#: Shell/UsersShell.php:224 -msgid "User was de-activated: {0}" -msgstr "" - -#: Shell/UsersShell.php:236 -msgid "Please enter a username or email." -msgstr "" - -#: Shell/UsersShell.php:244 -msgid "Please ask the user to check the email to continue with password reset process" -msgstr "" - -#: Shell/UsersShell.php:308 -msgid "Superuser added:" -msgstr "" - -#: Shell/UsersShell.php:310 -msgid "User added:" -msgstr "" - -#: Shell/UsersShell.php:312 -msgid "Id: {0}" -msgstr "" - -#: Shell/UsersShell.php:313 -msgid "Username: {0}" -msgstr "" - -#: Shell/UsersShell.php:314 -msgid "Email: {0}" -msgstr "" - -#: Shell/UsersShell.php:315 -msgid "Role: {0}" -msgstr "" - -#: Shell/UsersShell.php:316 -msgid "Password: {0}" -msgstr "" - -#: Shell/UsersShell.php:318 -msgid "User could not be added:" -msgstr "" - -#: Shell/UsersShell.php:321 -msgid "Field: {0} Error: {1}" -msgstr "" - -#: Shell/UsersShell.php:337 -msgid "The user was not found." -msgstr "" - -#: Shell/UsersShell.php:367 -msgid "The user {0} was not deleted. Please try again" -msgstr "" - -#: Shell/UsersShell.php:369 -msgid "The user {0} was deleted successfully" -msgstr "" - -#: Template/Email/html/reset_password.ctp:21 -#: Template/Email/html/social_account_validation.ctp:14 -#: Template/Email/html/validation.ctp:21 -#: Template/Email/text/reset_password.ctp:20 -#: Template/Email/text/social_account_validation.ctp:22 -#: Template/Email/text/validation.ctp:20 -msgid "Hi {0}" -msgstr "" - -#: Template/Email/html/reset_password.ctp:24 -msgid "Reset your password here" -msgstr "" - -#: Template/Email/html/reset_password.ctp:27 -#: Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 -msgid "If the link is not correctly displayed, please copy the following address in your web browser {0}" -msgstr "" - -#: Template/Email/html/reset_password.ctp:34 -#: Template/Email/html/social_account_validation.ctp:39 -#: Template/Email/html/validation.ctp:34 -#: Template/Email/text/reset_password.ctp:28 -#: Template/Email/text/social_account_validation.ctp:30 -#: Template/Email/text/validation.ctp:28 -msgid "Thank you" -msgstr "" - -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" -msgstr "" - -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" -msgstr "" - -#: Template/Email/text/reset_password.ctp:22 -#: Template/Email/text/validation.ctp:22 -msgid "Please copy the following address in your web browser {0}" -msgstr "" - -#: Template/Email/text/social_account_validation.ctp:24 -msgid "Please copy the following address in your web browser to activate your social login {0}" -msgstr "" - -#: Template/Users/add.ctp:13 -#: Template/Users/edit.ctp:16 -#: Template/Users/index.ctp:13;26 -#: Template/Users/view.ctp:15 -msgid "Actions" -msgstr "" - -#: Template/Users/add.ctp:15 -#: Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:23 -msgid "List Users" -msgstr "" - -#: Template/Users/add.ctp:21 -#: Template/Users/register.ctp:17 -msgid "Add User" -msgstr "" - -#: Template/Users/add.ctp:23 -#: Template/Users/edit.ctp:35 -#: Template/Users/index.ctp:22 -#: Template/Users/profile.ctp:30 -#: Template/Users/register.ctp:19 -#: Template/Users/view.ctp:33 -msgid "Username" -msgstr "" - -#: Template/Users/add.ctp:24 -#: Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:23 -#: Template/Users/profile.ctp:32 -#: Template/Users/register.ctp:20 -#: Template/Users/view.ctp:35 -msgid "Email" -msgstr "" - -#: Template/Users/add.ctp:25 -#: Template/Users/register.ctp:21 -msgid "Password" -msgstr "" - -#: Template/Users/add.ctp:26 -#: Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:24 -#: Template/Users/register.ctp:26 -msgid "First name" -msgstr "" - -#: Template/Users/add.ctp:27 -#: Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:25 -#: Template/Users/register.ctp:27 -msgid "Last name" -msgstr "" - -#: Template/Users/add.ctp:30 -#: Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:49;74 -msgid "Active" -msgstr "" - -#: Template/Users/add.ctp:34 -#: Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:57 -#: Template/Users/register.ctp:36 -#: Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:19 -msgid "Submit" -msgstr "" - -#: Template/Users/change_password.ctp:5 -msgid "Please enter the new password" -msgstr "" - -#: Template/Users/change_password.ctp:10 -msgid "Current password" -msgstr "" - -#: Template/Users/change_password.ctp:16 -msgid "New password" -msgstr "" - -#: Template/Users/change_password.ctp:21 -#: Template/Users/register.ctp:24 -msgid "Confirm password" -msgstr "" - -#: Template/Users/edit.ctp:21 -#: Template/Users/index.ctp:40 -msgid "Delete" -msgstr "" - -#: Template/Users/edit.ctp:23 -#: Template/Users/index.ctp:40 -#: Template/Users/view.ctp:21 -msgid "Are you sure you want to delete # {0}?" -msgstr "" - -#: Template/Users/edit.ctp:33 -#: Template/Users/view.ctp:17 -msgid "Edit User" -msgstr "" - -#: Template/Users/edit.ctp:39 -#: Template/Users/view.ctp:43 -msgid "Token" -msgstr "" - -#: Template/Users/edit.ctp:41 -msgid "Token expires" -msgstr "" - -#: Template/Users/edit.ctp:44 -msgid "API token" -msgstr "" - -#: Template/Users/edit.ctp:47 -msgid "Activation date" -msgstr "" - -#: Template/Users/edit.ctp:50 -msgid "TOS date" -msgstr "" - -#: Template/Users/edit.ctp:63 -msgid "Reset Google Authenticator Token" -msgstr "" - -#: Template/Users/edit.ctp:69 -msgid "Are you sure you want to reset token for user \"{0}\"?" -msgstr "" - -#: Template/Users/index.ctp:15 -msgid "New {0}" -msgstr "" - -#: Template/Users/index.ctp:37 -msgid "View" -msgstr "" - -#: Template/Users/index.ctp:38 -msgid "Change password" -msgstr "" - -#: Template/Users/index.ctp:39 -msgid "Edit" -msgstr "" - -#: Template/Users/index.ctp:49 -msgid "previous" -msgstr "" - -#: Template/Users/index.ctp:51 -msgid "next" -msgstr "" - -#: Template/Users/login.ctp:19 -msgid "Please enter your username and password" -msgstr "" - -#: Template/Users/login.ctp:29 -msgid "Remember me" -msgstr "" - -#: Template/Users/login.ctp:37 -msgid "Register" -msgstr "" - -#: Template/Users/login.ctp:43 -msgid "Reset Password" -msgstr "" - -#: Template/Users/login.ctp:48 -msgid "Login" -msgstr "" - -#: Template/Users/profile.ctp:21 -#: View/Helper/UserHelper.php:54 -msgid "{0} {1}" -msgstr "" - -#: Template/Users/profile.ctp:27 -msgid "Change Password" -msgstr "" - -#: Template/Users/profile.ctp:38 -#: Template/Users/view.ctp:68 -msgid "Social Accounts" -msgstr "" - -#: Template/Users/profile.ctp:42 -#: Template/Users/view.ctp:73 -msgid "Avatar" -msgstr "" - -#: Template/Users/profile.ctp:43 -#: Template/Users/view.ctp:72 -msgid "Provider" -msgstr "" - -#: Template/Users/profile.ctp:44 -msgid "Link" -msgstr "" - -#: Template/Users/profile.ctp:51 -msgid "Link to {0}" -msgstr "" - -#: Template/Users/register.ctp:29 -msgid "Accept TOS conditions?" -msgstr "" - -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" -msgstr "" - -#: Template/Users/resend_token_validation.ctp:15 -msgid "Resend Validation email" -msgstr "" - -#: Template/Users/resend_token_validation.ctp:17 -msgid "Email or username" -msgstr "" - -#: Template/Users/verify.ctp:13 -msgid "Verification Code" -msgstr "" - -#: Template/Users/verify.ctp:15 -msgid " Verify" -msgstr "" - -#: Template/Users/view.ctp:19 -msgid "Delete User" -msgstr "" - -#: Template/Users/view.ctp:24 -msgid "New User" -msgstr "" - -#: Template/Users/view.ctp:31 -msgid "Id" -msgstr "" - -#: Template/Users/view.ctp:37 -msgid "First Name" -msgstr "" - -#: Template/Users/view.ctp:39 -msgid "Last Name" -msgstr "" - -#: Template/Users/view.ctp:41 -msgid "Role" -msgstr "" - -#: Template/Users/view.ctp:45 -msgid "Api Token" -msgstr "" - -#: Template/Users/view.ctp:53 -msgid "Token Expires" -msgstr "" - -#: Template/Users/view.ctp:55 -msgid "Activation Date" -msgstr "" - -#: Template/Users/view.ctp:57 -msgid "Tos Date" -msgstr "" - -#: Template/Users/view.ctp:59;75 -msgid "Created" -msgstr "" - -#: Template/Users/view.ctp:61;76 -msgid "Modified" -msgstr "" - -#: View/Helper/UserHelper.php:45 -msgid "Sign in with" -msgstr "" - -#: View/Helper/UserHelper.php:48 -msgid "fa fa-{0}" -msgstr "" - -#: View/Helper/UserHelper.php:57 -msgid "btn btn-social btn-{0} " -msgstr "" - -#: View/Helper/UserHelper.php:106 -msgid "Logout" -msgstr "" - -#: View/Helper/UserHelper.php:123 -msgid "Welcome, {0}" -msgstr "" - -#: View/Helper/UserHelper.php:146 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" -msgstr "" - -#: View/Helper/UserHelper.php:205 -msgid "btn btn-social btn-{0}" -msgstr "" - -#: View/Helper/UserHelper.php:211 -msgid "Connected with {0}" -msgstr "" - -#: View/Helper/UserHelper.php:216 -msgid "Connect with {0}" -msgstr "" - diff --git a/src/Locale/ar_OM/Users.mo b/src/Locale/ar_OM/Users.mo deleted file mode 100644 index 8223903a8986118dcad05c4c848764badca7af6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18521 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 -# -msgid "" -msgstr "" -"Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2017-10-14 23:45+0000\n" -"PO-Revision-Date: 2018-11-13 12:43+0400\n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " -"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n" -"X-Generator: Poedit 2.2\n" -"Last-Translator: \n" -"Language: ar\n" - -#: Auth/SocialAuthenticate.php:456 -msgid "Provider cannot be empty" -msgstr "Ł„Ų§ ŁŠŁ…ŁƒŁ† ŲŖŲ±Łƒ Ł…Ų²ŁˆŲÆ Ų§Ł„Ų®ŲÆŁ…Ų© ŁŲ§Ų±Ųŗ" - -#: Controller/SocialAccountsController.php:52 -msgid "Account validated successfully" -msgstr "ŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų­Ų³Ų§ŲØ ŲØŁ†Ų¬Ų§Ų­" - -#: Controller/SocialAccountsController.php:54 -msgid "Account could not be validated" -msgstr "ŲŖŲ¹Ų°Ų± Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų­Ų³Ų§ŲØ" - -#: Controller/SocialAccountsController.php:57 -msgid "Invalid token and/or social account" -msgstr "Ų±Ł…Ų² Token ŲŗŁŠŲ± ŲµŲ§Ł„Ų­ Łˆ/ Ų£Łˆ Ų§Ł„Ų­Ų³Ų§ŲØ ŲŗŁŠŲ± ŲµŲ­ŁŠŲ­" - -#: Controller/SocialAccountsController.php:59;87 -msgid "Social Account already active" -msgstr "ŲŖŁ… ŲŖŁ†Ų“ŁŠŲ· Ų§Ł„Ų­Ų³Ų§ŲØ Ł…Ų³ŲØŁ‚Ų§Ł‹" - -#: Controller/SocialAccountsController.php:61 -msgid "Social Account could not be validated" -msgstr "ŲŖŲ¹Ų°Ų± Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų­Ų³Ų§ŲØ " - -#: Controller/SocialAccountsController.php:80 -msgid "Email sent successfully" -msgstr "ŲŖŁ… Ų„Ų±Ų³Ų§Ł„ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ ŲØŁ†Ų¬Ų§Ų­ " - -#: Controller/SocialAccountsController.php:82 -msgid "Email could not be sent" -msgstr "ŲŖŲ¹Ų°Ų± Ų„Ų±Ų³Ų§Ł„ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ" - -#: Controller/SocialAccountsController.php:85 -msgid "Invalid account" -msgstr "Ų­Ų³Ų§ŲØ ŲŗŁŠŲ± ŲµŲ§Ł„Ų­" - -#: Controller/SocialAccountsController.php:89 -msgid "Email could not be resent" -msgstr "Ł„Ų§ ŁŠŁ…ŁƒŁ† Ų§Ų±Ų³Ų§Ł„ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ " - -#: Controller/Component/RememberMeComponent.php:68 -msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" -msgstr "ŁŠŲ¬ŲØ Ų§Ł† ŁŠŁƒŁˆŁ† Ų§Ł„Ł…ŁŲŖŲ§Ų­ ŲØŲ·ŁˆŁ„ 32 ŲØŲ§ŁŠŲŖ" - -#: Controller/Component/UsersAuthComponent.php:204 -msgid "You can't enable email validation workflow if use_email is false" -msgstr "" -"Ł„Ų§ ŁŠŁ…ŁƒŁ† ŲŖŁŲ¹ŁŠŁ„ Ų§Ł„ŲŖŲ­Ł‚Ł‚ ŲØŲ§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ų§Ų°Ų§ ŁƒŲ§Ł† Ų§Ų³ŲŖŲ®ŲÆŲ§Ł… Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§ŁƒŲŖŲ±ŁˆŁ†ŁŠ ŲŗŁŠŲ± " -"Ł…ŁŲ¹Ł„ " - -#: Controller/Traits/LinkSocialTrait.php:54 -msgid "Could not associate account, please try again." -msgstr "ŲŖŲ¹Ų°Ų± Ų±ŲØŲ· Ų§Ł„Ų­Ų³Ų§ŲØ ŲŒ Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„Ł…Ų­Ų§ŁˆŁ„Ų© Ł…Ų±Ł‡ Ų£Ų®Ų±Ł‰." - -#: Controller/Traits/LinkSocialTrait.php:77 -msgid "Social account was associated." -msgstr "ŲŖŁ… Ų±ŲØŲ· Ų§Ł„Ų­Ų³Ų§ŲØ Ł…Ų³ŲØŁ‚Ų§Ł‹" - -#: Controller/Traits/LoginTrait.php:104 -msgid "Issues trying to log in with your social account" -msgstr "ŲŖŲ¹Ų°Ų± ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„ ŲØŲ§Ų³ŲŖŲ®ŲÆŲ§Ł… Ų­Ų³Ų§ŲØŁƒ" - -#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 -msgid "Please enter your email" -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ ŲØŲ±ŁŠŲÆŁƒ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ" - -#: Controller/Traits/LoginTrait.php:120 -msgid "" -"Your user has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Ł„Ł… ŁŠŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ų§Ł„Ų®Ų§Ųµ ŲØŁƒ ŲØŲ¹ŲÆ. Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁˆŲ§Ų±ŲÆ " -"Ł„Ł„Ų­ŲµŁˆŁ„ Ų¹Ł„ŁŠ ŲŖŲ¹Ł„ŁŠŁ…Ų§ŲŖ" - -#: Controller/Traits/LoginTrait.php:125 -msgid "" -"Your social account has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Ł„Ł… ŁŠŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų­Ų³Ų§ŲØŁƒ Ų§Ł„Ų§Ų¬ŲŖŁ…Ų§Ų¹ŁŠ ŲØŲ¹ŲÆ. Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁˆŲ§Ų±ŲÆ " -"Ł„Ł„Ų­ŲµŁˆŁ„ Ų¹Ł„ŁŠ ŲŖŲ¹Ł„ŁŠŁ…Ų§ŲŖ" - -#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 -msgid "Invalid reCaptcha" -msgstr "reCaptcha ŲŗŁŠŲ± ŲµŲ§Ł„Ų­Ł‡" - -#: Controller/Traits/LoginTrait.php:191 -msgid "You are already logged in" -msgstr "ŲŖŁ… ŲŖŲ³Ų¬ŁŠŁ„ ŲÆŲ®ŁˆŁ„Łƒ Ł…Ų³ŲØŁ‚Ų§Ł‹" - -#: Controller/Traits/LoginTrait.php:212 -msgid "Please enable Google Authenticator first." -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” ŲŖŁ…ŁƒŁŠŁ† Ų£ŲÆŲ§Ł‡ Ł…ŲµŲ§ŲÆŁ‚Ł‡ Google Ų£ŁˆŁ„Ų§." - -#: Controller/Traits/LoginTrait.php:287 -msgid "Verification code is invalid. Try again" -msgstr "Ų±Ł…Ų² Ų§Ł„ŲŖŲ­Ł‚Ł‚ ŲŗŁŠŲ± ŲµŲ§Ł„Ų­. Ų­Ų§ŁˆŁ„ Ł…Ų±Ų© Ų£Ų®Ų±Ł‰" - -#: Controller/Traits/LoginTrait.php:340 -msgid "Username or password is incorrect" -msgstr "Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ų£Łˆ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± ŲŗŁŠŲ± ŲµŲ­ŁŠŲ­Ł‡" - -#: Controller/Traits/LoginTrait.php:363 -msgid "You've successfully logged out" -msgstr "Ł„Ł‚ŲÆ Ł‚Ł…ŲŖ ŲØŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„Ų®Ų±ŁˆŲ¬ ŲØŁ†Ų¬Ų§Ų­" - -#: Controller/Traits/PasswordManagementTrait.php:49;82 -#: Controller/Traits/ProfileTrait.php:50 -msgid "User was not found" -msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„ŁŠ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Controller/Traits/PasswordManagementTrait.php:70;78;86 -msgid "Password could not be changed" -msgstr "ŲŖŲ¹Ų°Ų± ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Controller/Traits/PasswordManagementTrait.php:74 -msgid "Password has been changed successfully" -msgstr "ŲŖŁ… ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± ŲØŁ†Ų¬Ų§Ų­" - -#: Controller/Traits/PasswordManagementTrait.php:84 -msgid "{0}" -msgstr "{0}" - -#: Controller/Traits/PasswordManagementTrait.php:127 -msgid "Please check your email to continue with password reset process" -msgstr "" -"ŁŠŲ±Ų¬Ł‰ Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ų§Ł„Ų®Ų§Ųµ ŲØŁƒ Ł„Ł…ŲŖŲ§ŲØŲ¹Ł‡ Ų¹Ł…Ł„ŁŠŁ‡ Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 -msgid "The password token could not be generated. Please try again" -msgstr "ŲŖŲ¹Ų°Ų± Ų„Ł†Ų“Ų§Ų” Ų§Ł„Ų±Ł…Ų² Ų§Ł„Ł…Ł…ŁŠŲ² Ł„ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±. Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„Ł…Ų­Ų§ŁˆŁ„Ų© Ł…Ų±Ł‡ Ų£Ų®Ų±Ł‰" - -#: Controller/Traits/PasswordManagementTrait.php:136 -#: Controller/Traits/UserValidationTrait.php:107 -msgid "User {0} was not found" -msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„ŁŠ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… {0}" - -#: Controller/Traits/PasswordManagementTrait.php:138 -msgid "The user is not active" -msgstr "Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… ŲŗŁŠŲ± Ł†Ų“Ų·" - -#: Controller/Traits/PasswordManagementTrait.php:140 -#: Controller/Traits/UserValidationTrait.php:102;111 -msgid "Token could not be reset" -msgstr "ŲŖŲ¹Ų°Ų± Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† Ų§Ł„Ų±Ł…Ų² Ų§Ł„Ł…Ł…ŁŠŲ²" - -#: Controller/Traits/PasswordManagementTrait.php:164 -msgid "Google Authenticator token was successfully reset" -msgstr "ŲŖŁ…ŲŖ Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† Ų±Ł…Ų² Ł…ŲµŲ§ŲÆŁ‚Ł‡ Google ŲØŁ†Ų¬Ų§Ų­" - -#: Controller/Traits/ProfileTrait.php:54 -msgid "Not authorized, please login first" -msgstr "ŲŗŁŠŲ± Ł…ŲµŲ±Ų­ ŲØŁ‡ ŲŒ Ų§Ł„Ų±Ų¬Ų§Ų” ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„ Ų£ŁˆŁ„Ų§" - -#: Controller/Traits/RegisterTrait.php:43 -msgid "You must log out to register a new user account" -msgstr "ŁŠŲ¬ŲØ ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„Ų®Ų±ŁˆŲ¬ Ł„ŲŖŲ³Ų¬ŁŠŁ„ Ų­Ų³Ų§ŲØ Ł…Ų³ŲŖŲ®ŲÆŁ… Ų¬ŲÆŁŠŲÆ" - -#: Controller/Traits/RegisterTrait.php:89 -msgid "The user could not be saved" -msgstr "ŲŖŲ¹Ų°Ų± Ų­ŁŲø Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Controller/Traits/RegisterTrait.php:123 -msgid "You have registered successfully, please log in" -msgstr "Ł„Ł‚ŲÆ Ł‚Ł…ŲŖ ŲØŲ§Ł„ŲŖŲ³Ų¬ŁŠŁ„ ŲØŁ†Ų¬Ų§Ų­ ŲŒ Ų§Ł„Ų±Ų¬Ų§Ų” ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„" - -#: Controller/Traits/RegisterTrait.php:125 -msgid "Please validate your account before log in" -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” ŲŖŁ†Ų“ŁŠŲ· Ų­Ų³Ų§ŲØŁƒ Ł‚ŲØŁ„ ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„" - -#: Controller/Traits/SimpleCrudTrait.php:77;107 -msgid "The {0} has been saved" -msgstr "ŲŖŁ… Ų­ŁŲø {0}" - -#: Controller/Traits/SimpleCrudTrait.php:81;111 -msgid "The {0} could not be saved" -msgstr "ŲŖŲ¹Ų°Ų± Ų­ŁŲø {0}" - -#: Controller/Traits/SimpleCrudTrait.php:131 -msgid "The {0} has been deleted" -msgstr "ŲŖŁ… Ų­Ų°Ł {0}" - -#: Controller/Traits/SimpleCrudTrait.php:133 -msgid "The {0} could not be deleted" -msgstr "ŲŖŲ¹Ų°Ų± Ų­Ų°Ł {0}" - -#: Controller/Traits/SocialTrait.php:40 -msgid "The reCaptcha could not be validated" -msgstr "ŲŖŲ¹Ų°Ų± Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© reCaptcha" - -#: Controller/Traits/UserValidationTrait.php:43 -msgid "User account validated successfully" -msgstr "ŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų­Ų³Ų§ŲØ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… ŲØŁ†Ų¬Ų§Ų­" - -#: Controller/Traits/UserValidationTrait.php:45 -msgid "User account could not be validated" -msgstr "ŲŖŲ¹Ų°Ų± Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų­Ų³Ų§ŲØ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Controller/Traits/UserValidationTrait.php:48 -msgid "User already active" -msgstr "Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł†Ų“Ų· ŲØŲ§Ł„ŁŲ¹Ł„" - -#: Controller/Traits/UserValidationTrait.php:54 -msgid "Reset password token was validated successfully" -msgstr "ŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų±Ł…Ų² Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± ŲØŁ†Ų¬Ų§Ų­" - -#: Controller/Traits/UserValidationTrait.php:62 -msgid "Reset password token could not be validated" -msgstr "ŲŖŲ¹Ų°Ų± Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų±Ł…Ų² Ų§Ł„Ł…Ł…ŁŠŲ² Ł„Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Controller/Traits/UserValidationTrait.php:66 -msgid "Invalid validation type" -msgstr "ŁˆŲ³ŁŠŁ„Ų© Ų§Ł„ŲŖŲ­Ł‚Ł‚ ŲŗŁŠŲ± ŲµŲ§Ł„Ų­Ų©" - -#: Controller/Traits/UserValidationTrait.php:69 -msgid "Invalid token or user account already validated" -msgstr "Ų§Ł„Ų±Ł…Ų² (token) ŲŗŁŠŲ± ŲµŲ­ŁŠŲ­ Ų§Łˆ ŲŖŁ… Ų§Ų³ŲŖŲ®ŲÆŲ§Ł…Ł‡ Ł…Ł† Ł‚ŲØŁ„" - -#: Controller/Traits/UserValidationTrait.php:71 -msgid "Token already expired" -msgstr "Ų§Ł„Ų±Ł…Ų² token Ų§Ł†ŲŖŁ‡ŲŖ ŲµŁ„Ų§Ų­ŁŠŲŖŁ‡ " - -#: Controller/Traits/UserValidationTrait.php:97 -msgid "Token has been reset successfully. Please check your email." -msgstr "ŲŖŁ… Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† token ŲØŁ†Ų¬Ų§Ų­. ŁŠŲ±Ų¬Ł‰ Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲØŲ±ŁŠŲÆŁƒ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ." - -#: Controller/Traits/UserValidationTrait.php:109 -msgid "User {0} is already active" -msgstr "Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… {0} Ł†Ų“Ų· ŲØŲ§Ł„ŁŲ¹Ł„" - -#: Mailer/UsersMailer.php:34 -msgid "Your account validation link" -msgstr "Ų±Ų§ŲØŲ· Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† Ų§Ł„Ų­Ų³Ų§ŲØŁƒ" - -#: Mailer/UsersMailer.php:52 -msgid "{0}Your reset password link" -msgstr "{0} Ų±Ų§ŲØŲ· Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Mailer/UsersMailer.php:75 -msgid "{0}Your social account validation link" -msgstr "{0} Ų±Ų§ŲØŲ· Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų­Ų³Ų§ŲØ" - -#: Model/Behavior/AuthFinderBehavior.php:49 -msgid "Missing 'username' in options data" -msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„Ł‰ Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Model/Behavior/LinkSocialBehavior.php:53 -msgid "Social account already associated to another user" -msgstr "Ų§Ł„Ų­Ų³Ų§ŲØ Ł…Ų±ŲŖŲØŲ· ŲØŲ§Ł„ŁŲ¹Ł„ ŲØŁ…Ų³ŲŖŲ®ŲÆŁ… Ų¢Ų®Ų±" - -#: Model/Behavior/PasswordBehavior.php:45 -msgid "Reference cannot be null" -msgstr "Ł„Ų§ ŁŠŁ…ŁƒŁ† Ų§Ł† ŁŠŁƒŁˆŁ† Ų§Ł„Ł…Ų±Ų¬Ų¹ ŁŲ§Ų±ŲŗŲ§" - -#: Model/Behavior/PasswordBehavior.php:50 -msgid "Token expiration cannot be empty" -msgstr "Ł„Ų§ ŁŠŁ…ŁƒŁ† ŲŖŲ±Łƒ Ų­Ł‚Ł„ Ų§Ł†ŲŖŁ‡Ų§Ų” ŲµŁ„Ų§Ų­ŁŠŲ© Token ŁŲ§Ų±ŲŗŲ§Ł‹ " - -#: Model/Behavior/PasswordBehavior.php:56;117 -msgid "User not found" -msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„ŁŠ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Model/Behavior/PasswordBehavior.php:60 -#: Model/Behavior/RegisterBehavior.php:112;205 -msgid "User account already validated" -msgstr "ŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų­Ų³Ų§ŲØ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Model/Behavior/PasswordBehavior.php:67 -msgid "User not active" -msgstr "Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… ŲŗŁŠŲ± Ł†Ų“Ų·" - -#: Model/Behavior/PasswordBehavior.php:122 -msgid "The current password does not match" -msgstr "Ł„Ų§ ŲŖŲŖŲ·Ų§ŲØŁ‚ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų§Ł„Ų­Ų§Ł„ŁŠŲ©" - -#: Model/Behavior/PasswordBehavior.php:125 -msgid "You cannot use the current password as the new one" -msgstr "Ł„Ų§ ŁŠŁ…ŁƒŁ†Łƒ Ų§Ų³ŲŖŲ®ŲÆŲ§Ł… ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų§Ł„Ų­Ų§Ł„ŁŠŲ© ŁƒŁ€ ŁƒŁ„Ł…Ų© Ų³Ų± Ų¬ŲÆŁŠŲÆŲ©" - -#: Model/Behavior/RegisterBehavior.php:90 -msgid "User not found for the given token and email." -msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„Ł‰ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł„Ł‡Ų°Ų§ Ų§Ł„Ų±Ł…Ų² Łˆ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ " - -#: Model/Behavior/RegisterBehavior.php:93 -msgid "Token has already expired user with no token" -msgstr "Ų§Ł„Ų±Ł…Ų² Token Ų§Ł†ŲŖŁ‡ŲŖ ŲµŁ„Ų§Ų­ŁŠŲŖŁ‡, Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… ŲØŲÆŁˆŁ† Token Ų§Ł„Ų¢Ł† " - -#: Model/Behavior/SocialAccountBehavior.php:103;130 -msgid "Account already validated" -msgstr "ŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų­Ų³Ų§ŲØ" - -#: Model/Behavior/SocialAccountBehavior.php:106;133 -msgid "Account not found for the given token and email." -msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„Ł‰ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł„Ł‡Ų°Ų§ Ų§Ł„Ų±Ł…Ų² Łˆ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ " - -#: Model/Behavior/SocialBehavior.php:82 -msgid "Unable to login user with reference {0}" -msgstr "ŲŗŁŠŲ± Ł‚Ų§ŲÆŲ± Ų¹Ł„ŁŠ ŲŖŲ³Ų¬ŁŠŁ„ ŲÆŲ®ŁˆŁ„ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ Ų§Ł„Ł…Ų±Ų¬Ų¹ {0}" - -#: Model/Behavior/SocialBehavior.php:121 -msgid "Email not present" -msgstr "Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ ŲŗŁŠŲ± Ł…ŁˆŲ¬ŁˆŲÆ" - -#: Model/Table/UsersTable.php:81 -msgid "Your password does not match your confirm password. Please try again" -msgstr "" -"Ł„Ų§ ŲŖŲŖŲ·Ų§ŲØŁ‚ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų§Ł„Ų®Ų§ŲµŲ© ŲØŁƒ Ł…Ų¹ ŲŖŲ§ŁƒŁŠŲÆ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±. Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„Ł…Ų­Ų§ŁˆŁ„Ų© Ł…Ų±Ł‡ " -"Ų£Ų®Ų±Ł‰" - -#: Model/Table/UsersTable.php:173 -msgid "Username already exists" -msgstr "Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…ŁˆŲ¬ŁˆŲÆ ŲØŲ§Ł„ŁŲ¹Ł„" - -#: Model/Table/UsersTable.php:179 -msgid "Email already exists" -msgstr "Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ł…ŁˆŲ¬ŁˆŲÆ ŲØŲ§Ł„ŁŲ¹Ł„" - -#: Shell/UsersShell.php:58 -msgid "Utilities for CakeDC Users Plugin" -msgstr "Ų§Ł„Ų£ŲÆŁˆŲ§ŲŖ Ų§Ł„Ł…Ų³Ų§Ų¹ŲÆŲ© Ł„Ų„Ų¶Ų§ŁŲ© CakeDC/Users " - -#: Shell/UsersShell.php:60 -msgid "Activate an specific user" -msgstr "ŲŖŁ†Ų“ŁŠŲ· Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ŁŠŁ†" - -#: Shell/UsersShell.php:63 -msgid "Add a new superadmin user for testing purposes" -msgstr "Ų£Ų¶Ų§ŁŁ‡ Ł…Ų³ŲŖŲ®ŲÆŁ… Ų¬ŲÆŁŠŲÆ super admin Ł„Ų£ŲŗŲ±Ų§Ų¶ Ų§Ł„Ų§Ų®ŲŖŲØŲ§Ų±" - -#: Shell/UsersShell.php:66 -msgid "Add a new user" -msgstr "Ų£Ų¶Ų§ŁŁ‡ Ł…Ų³ŲŖŲ®ŲÆŁ… Ų¬ŲÆŁŠŲÆ" - -#: Shell/UsersShell.php:69 -msgid "Change the role for an specific user" -msgstr "ŲŖŲŗŁŠŁŠŲ± ŲÆŁˆŲ± Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ŁŠŁ†" - -#: Shell/UsersShell.php:72 -msgid "Deactivate an specific user" -msgstr "Ų„Ł„ŲŗŲ§Ų” ŲŖŁ†Ų“ŁŠŲ· Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ŁŠŁ†" - -#: Shell/UsersShell.php:75 -msgid "Delete an specific user" -msgstr "Ų­Ų°Ł Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ŁŠŁ†" - -#: Shell/UsersShell.php:78 -msgid "Reset the password via email" -msgstr "Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų¹ŲØŲ± Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ" - -#: Shell/UsersShell.php:81 -msgid "Reset the password for all users" -msgstr "Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ł„ŁƒŲ§ŁŲ© Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…ŁŠŁ†" - -#: Shell/UsersShell.php:84 -msgid "Reset the password for an specific user" -msgstr "Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ŁŠŁ†" - -#: Shell/UsersShell.php:133;159 -msgid "Please enter a password." -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ ŁƒŁ„Ł…Ų© Ł…Ų±ŁˆŲ±" - -#: Shell/UsersShell.php:137 -msgid "Password changed for all users" -msgstr "ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ł„ŁƒŲ§ŁŲ© Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…ŁŠŁ†" - -#: Shell/UsersShell.php:138;166 -msgid "New password: {0}" -msgstr "ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų§Ł„Ų¬ŲÆŁŠŲÆŲ©: {0}" - -#: Shell/UsersShell.php:156;184;262;359 -msgid "Please enter a username." -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų§ŲÆŲ®Ų§Ł„ Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…." - -#: Shell/UsersShell.php:165 -msgid "Password changed for user: {0}" -msgstr "ŲŖŁ… ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ł„Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…: {0}" - -#: Shell/UsersShell.php:187 -msgid "Please enter a role." -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ ŲÆŁˆŲ±." - -#: Shell/UsersShell.php:193 -msgid "Role changed for user: {0}" -msgstr "ŲŖŁ… ŲŖŲŗŁŠŁŠŲ± Ų§Ł„ŲÆŁˆŲ± Ł„Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…: {0}" - -#: Shell/UsersShell.php:194 -msgid "New role: {0}" -msgstr "ŲÆŁˆŲ± Ų¬ŲÆŁŠŲÆ: {0}" - -#: Shell/UsersShell.php:209 -msgid "User was activated: {0}" -msgstr "ŲŖŁ… ŲŖŁ†Ų“ŁŠŲ· Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…: {0}" - -#: Shell/UsersShell.php:224 -msgid "User was de-activated: {0}" -msgstr "ŲŖŁ… Ų„Ł„ŲŗŲ§Ų” ŲŖŁ†Ų“ŁŠŲ· Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…: {0}" - -#: Shell/UsersShell.php:236 -msgid "Please enter a username or email." -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ų£Łˆ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ." - -#: Shell/UsersShell.php:244 -msgid "" -"Please ask the user to check the email to continue with password reset " -"process" -msgstr "" -"Ł…Ł† ŁŲ¶Ł„Łƒ Ų§Ų·Ł„ŲØ Ł…Ł† Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ł„Ł…ŲŖŲ§ŲØŲ¹Ł‡ Ų¹Ł…Ł„ŁŠŁ‡ Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† " -"ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Shell/UsersShell.php:308 -msgid "Superuser added:" -msgstr "ŲŖŁ… Ų„Ų¶Ų§ŁŲ© SuperUser" - -#: Shell/UsersShell.php:310 -msgid "User added:" -msgstr "ŲŖŁ… Ų„Ų¶Ų§ŁŲ© Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Shell/UsersShell.php:312 -msgid "Id: {0}" -msgstr "Ų§Ł„Ł…Ų¹Ų±Ł: {0}" - -#: Shell/UsersShell.php:313 -msgid "Username: {0}" -msgstr "Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…: {0}" - -#: Shell/UsersShell.php:314 -msgid "Email: {0}" -msgstr "Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ: {0}" - -#: Shell/UsersShell.php:315 -msgid "Role: {0}" -msgstr "Ų§Ł„ŲÆŁˆŲ±: {0}" - -#: Shell/UsersShell.php:316 -msgid "Password: {0}" -msgstr "ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±: {0}" - -#: Shell/UsersShell.php:318 -msgid "User could not be added:" -msgstr "ŲŖŲ¹Ų°Ų± Ų£Ų¶Ų§ŁŁ‡ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…:" - -#: Shell/UsersShell.php:321 -msgid "Field: {0} Error: {1}" -msgstr "Ų§Ł„Ų­Ł‚Ł„: {0} Ų®Ų·Ų§: {1}" - -#: Shell/UsersShell.php:337 -msgid "The user was not found." -msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„ŁŠ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…." - -#: Shell/UsersShell.php:367 -msgid "The user {0} was not deleted. Please try again" -msgstr "Ł„Ł… ŁŠŲŖŁ… Ų­Ų°Ł Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… {0}. Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„Ł…Ų­Ų§ŁˆŁ„Ų© Ł…Ų±Ł‡ Ų£Ų®Ų±Ł‰" - -#: Shell/UsersShell.php:369 -msgid "The user {0} was deleted successfully" -msgstr "ŲŖŁ… Ų­Ų°Ł Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… {0} ŲØŁ†Ų¬Ų§Ų­" - -#: Template/Email/html/reset_password.ctp:21 -#: Template/Email/html/social_account_validation.ctp:14 -#: Template/Email/html/validation.ctp:21 -#: Template/Email/text/reset_password.ctp:20 -#: Template/Email/text/social_account_validation.ctp:22 -#: Template/Email/text/validation.ctp:20 -msgid "Hi {0}" -msgstr "Ł…Ų±Ų­ŲØŲ§ {0}" - -#: Template/Email/html/reset_password.ctp:24 -msgid "Reset your password here" -msgstr "Ų£Ų¹ŲÆ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ł…Ł† Ł‡Ł†Ų§" - -#: Template/Email/html/reset_password.ctp:27 -#: Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 -msgid "" -"If the link is not correctly displayed, please copy the following address in " -"your web browser {0}" -msgstr "" -"Ų„Ų°Ų§ Ł„Ł… ŁŠŲŖŁ… Ų¹Ų±Ų¶ Ų§Ł„Ų±Ų§ŲØŲ· ŲØŲ“ŁƒŁ„ ŲµŲ­ŁŠŲ­ ŲŒ Ų§Ł„Ų±Ų¬Ų§Ų” Ł†Ų³Ų® Ų§Ł„Ų¹Ł†ŁˆŲ§Ł† Ų§Ł„ŲŖŲ§Ł„ŁŠ ŁŁŠ Ł…Ų³ŲŖŲ¹Ų±Ų¶ ŁˆŁŠŲØ " -"{0}" - -#: Template/Email/html/reset_password.ctp:34 -#: Template/Email/html/social_account_validation.ctp:39 -#: Template/Email/html/validation.ctp:34 -#: Template/Email/text/reset_password.ctp:28 -#: Template/Email/text/social_account_validation.ctp:30 -#: Template/Email/text/validation.ctp:28 -msgid "Thank you" -msgstr "Ų“ŁƒŲ±Ų§Ł‹ Ł„Łƒ" - -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" -msgstr "ŲŖŁŲ¹ŁŠŁ„ ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„ ŲØŲ§Ų³ŲŖŲ®ŲÆŲ§Ł… Ų“ŲØŁƒŲ§ŲŖ Ų§Ł„ŲŖŁˆŲ§ŲµŁ„ Ų§Ł„Ų§Ų¬ŲŖŁ…Ų§Ų¹ŁŠŲ§" - -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" -msgstr "ŲŖŁŲ¹ŁŠŁ„ Ų­Ų³Ų§ŲØŁƒ Ł…Ł† Ł‡Ł†Ų§" - -#: Template/Email/text/reset_password.ctp:22 -#: Template/Email/text/validation.ctp:22 -msgid "Please copy the following address in your web browser {0}" -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ł†Ų³Ų® Ų§Ł„Ų¹Ł†ŁˆŲ§Ł† Ų§Ł„ŲŖŲ§Ł„ŁŠ ŁŁŠ Ł…Ų³ŲŖŲ¹Ų±Ų¶ ŁˆŁŠŲØ {0}" - -#: Template/Email/text/social_account_validation.ctp:24 -msgid "" -"Please copy the following address in your web browser to activate your " -"social login {0}" -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ł†Ų³Ų® Ų§Ł„Ų¹Ł†ŁˆŲ§Ł† Ų§Ł„ŲŖŲ§Ł„ŁŠ ŁŁŠ Ł…ŲŖŲµŁŲ­ Ų§Ł„ŁˆŁŠŲØ Ų§Ł„Ų®Ų§Ųµ ŲØŁƒ Ł„ŲŖŁ†Ų“ŁŠŲ· Ų­Ų³Ų§ŲØŁƒ {0}" - -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 -msgid "Actions" -msgstr "Ų§Ł„Ų§Ų¬Ų±Ų§Ų”Ų§ŲŖ" - -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:23 -msgid "List Users" -msgstr "Ł‚Ų§Ų¦Ł…Ų© Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…ŁŠŁ†" - -#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 -msgid "Add User" -msgstr "Ų„Ų¶Ų§ŁŲ© Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 -#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 -#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 -msgid "Username" -msgstr "Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 -#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 -msgid "Email" -msgstr "Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ" - -#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 -msgid "Password" -msgstr "ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 -msgid "First name" -msgstr "Ų§Ł„Ų§Ų³Ł… Ų§Ł„Ų£ŁˆŁ„" - -#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 -msgid "Last name" -msgstr "Ų§Ł„Ų§Ų³Ł… Ų§Ł„Ų£Ų®ŁŠŲ±" - -#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:49;74 -msgid "Active" -msgstr "ŁŲ¹Ų§Ł„" - -#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 -#: Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:19 -msgid "Submit" -msgstr "Ų„Ų±Ų³Ų§Ł„" - -#: Template/Users/change_password.ctp:5 -msgid "Please enter the new password" -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų§Ł„Ų¬ŲÆŁŠŲÆŲ©" - -#: Template/Users/change_password.ctp:10 -msgid "Current password" -msgstr "ŁƒŁ„Ł…Ł‡ Ų§Ł„Ų³Ų± Ų§Ł„Ų­Ų§Ł„ŁŠŲ©" - -#: Template/Users/change_password.ctp:16 -msgid "New password" -msgstr "ŁƒŁ„Ł…Ł‡ Ų§Ł„Ų³Ų± Ų§Ł„Ų¬ŲÆŁŠŲÆŲ©" - -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 -msgid "Confirm password" -msgstr "ŲŖŲ§ŁƒŁŠŲÆ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 -msgid "Delete" -msgstr "Ų­Ų°Ł" - -#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:21 -msgid "Are you sure you want to delete # {0}?" -msgstr "Ł‡Ł„ ŲŖŲ±ŁŠŲÆ ŲØŲ§Ł„ŲŖŲ§ŁƒŁŠŲÆ Ų­Ų°Ł # {0} ŲŸ" - -#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 -msgid "Edit User" -msgstr "ŲŖŲ¹ŲÆŁŠŁ„ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 -msgid "Token" -msgstr "Ų§Ł„Ų±Ł…Ų² Token" - -#: Template/Users/edit.ctp:41 -msgid "Token expires" -msgstr "Ų§Ł†ŲŖŁ‡Ų§Ų” ŲµŁ„Ų§Ų­ŁŠŁ‡ Ų§Ł„Ų±Ł…Ų² Token" - -#: Template/Users/edit.ctp:44 -msgid "API token" -msgstr "API token" - -#: Template/Users/edit.ctp:47 -msgid "Activation date" -msgstr "ŲŖŲ§Ų±ŁŠŲ® Ų§Ł„ŲŖŁŲ¹ŁŠŁ„" - -#: Template/Users/edit.ctp:50 -msgid "TOS date" -msgstr "ŲŖŲ§Ų±ŁŠŲ® Ų§Ł„Ł…ŁˆŲ§ŁŁ‚Ų© Ų¹Ł„Ł‰ Ų“Ų±ŁˆŲ· Ų§Ł„Ų§Ų³ŲŖŲ®ŲÆŲ§Ł…" - -#: Template/Users/edit.ctp:63 -msgid "Reset Google Authenticator Token" -msgstr "Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† Ų±Ł…Ų² Ł…ŲµŲ§ŲÆŁ‚Ł‡ Google" - -#: Template/Users/edit.ctp:69 -msgid "Are you sure you want to reset token for user \"{0}\"?" -msgstr "Ł‡Ł„ ŲŖŲ±ŁŠŲÆ ŲØŲ§Ł„ŲŖŲ§ŁƒŁŠŲÆ Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† Token Ł„Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… \"{0}\" ŲŸ" - -#: Template/Users/index.ctp:15 -msgid "New {0}" -msgstr "{0} Ų¬ŲÆŁŠŲÆ" - -#: Template/Users/index.ctp:37 -msgid "View" -msgstr "Ų¹Ų±Ų¶" - -#: Template/Users/index.ctp:38 -msgid "Change password" -msgstr "ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ų© Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Template/Users/index.ctp:39 -msgid "Edit" -msgstr "ŲŖŲ­Ų±ŁŠŲ±" - -#: Template/Users/index.ctp:49 -msgid "previous" -msgstr "Ų§Ł„Ų³Ų§ŲØŁ‚" - -#: Template/Users/index.ctp:51 -msgid "next" -msgstr "Ų§Ł„ŲŖŲ§Ł„ŁŠ" - -#: Template/Users/login.ctp:19 -msgid "Please enter your username and password" -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… ŁˆŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Template/Users/login.ctp:29 -msgid "Remember me" -msgstr "ŲŖŲ°ŁƒŲ±Ł†ŁŠ" - -#: Template/Users/login.ctp:37 -msgid "Register" -msgstr "Ų§Ł„ŲŖŲ³Ų¬ŁŠŁ„" - -#: Template/Users/login.ctp:43 -msgid "Reset Password" -msgstr "Ų„Ų¹Ų§ŲÆŲ© ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ų© Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Template/Users/login.ctp:48 -msgid "Login" -msgstr "ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„" - -#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 -msgid "{0} {1}" -msgstr "{0} {1}" - -#: Template/Users/profile.ctp:27 -msgid "Change Password" -msgstr "ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 -msgid "Social Accounts" -msgstr "Ų­Ų³Ų§ŲØŲ§ŲŖ Ų§Ł„ŲŖŁˆŲ§ŲµŁ„ Ų§Ł„Ų§Ų¬ŲŖŁ…Ų§Ų¹ŁŠ" - -#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 -msgid "Avatar" -msgstr "Ų§Ł„ŲµŁˆŲ±Ų© Ų§Ł„Ų“Ų®ŲµŁŠŲ©" - -#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 -msgid "Provider" -msgstr "Ų§Ł„Ł…Ų²ŁˆŲÆ" - -#: Template/Users/profile.ctp:44 -msgid "Link" -msgstr "Ų±Ų§ŲØŲ·" - -#: Template/Users/profile.ctp:51 -msgid "Link to {0}" -msgstr "Ų§Ł„Ų§Ų±ŲŖŲØŲ§Ų· ŲØ {0}" - -#: Template/Users/register.ctp:29 -msgid "Accept TOS conditions?" -msgstr "Ł‡Ł„ ŲŖŁ‚ŲØŁ„ Ų“Ų±ŁˆŲ· Ų§Ł„Ų§Ų³ŲŖŲ®ŲÆŲ§Ł… ŲŸ" - -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" -msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ ŲØŲ±ŁŠŲÆŁƒ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ł„Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" - -#: Template/Users/resend_token_validation.ctp:15 -msgid "Resend Validation email" -msgstr "Ų£Ų¹Ų§ŲÆŲ© ŲŖŁ†Ų“ŁŠŲ· Ų§Ł„Ų­Ų³Ų§ŲØ Ų¹ŲØŲ± Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ" - -#: Template/Users/resend_token_validation.ctp:17 -msgid "Email or username" -msgstr "Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ų£Łˆ Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Template/Users/verify.ctp:13 -msgid "Verification Code" -msgstr "Ų±Ł…Ų² Ų§Ł„ŲŖŲ­Ł‚Ł‚" - -#: Template/Users/verify.ctp:15 -msgid "" -" " -"Verify" -msgstr "" -" " -"ŲŖŲ£ŁƒŁŠŲÆ Ų§Ł„ŲŖŲ­Ł‚Ł‚" - -#: Template/Users/view.ctp:19 -msgid "Delete User" -msgstr "Ų­Ų°Ł Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" - -#: Template/Users/view.ctp:24 -msgid "New User" -msgstr "Ł…Ų³ŲŖŲ®ŲÆŁ… Ų¬ŲÆŁŠŲÆ" - -#: Template/Users/view.ctp:31 -msgid "Id" -msgstr "Ų§Ł„Ł…Ų¹Ų±Ł" - -#: Template/Users/view.ctp:37 -msgid "First Name" -msgstr "Ų§Ł„Ų§Ų³Ł… Ų§Ł„Ų§ŁˆŁ„" - -#: Template/Users/view.ctp:39 -msgid "Last Name" -msgstr "Ų§Ł„Ų§Ų³Ł… Ų§Ł„Ų§Ų®ŁŠŲ±" - -#: Template/Users/view.ctp:41 -msgid "Role" -msgstr "Ų§Ł„ŲÆŁˆŲ±" - -#: Template/Users/view.ctp:45 -msgid "Api Token" -msgstr "API token" - -#: Template/Users/view.ctp:53 -msgid "Token Expires" -msgstr "Token Expires" - -#: Template/Users/view.ctp:55 -msgid "Activation Date" -msgstr "ŲŖŲ§Ų±ŁŠŲ® Ų§Ł„ŲŖŁŲ¹ŁŠŁ„" - -#: Template/Users/view.ctp:57 -msgid "Tos Date" -msgstr "ŲŖŲ§Ų±ŁŠŲ® Ų§Ł„Ł…ŁˆŲ§ŁŁ‚Ų© Ų¹Ł„Ł‰ Ų“Ų±ŁˆŲ· Ų§Ł„Ų§Ų³ŲŖŲ®ŲÆŲ§Ł…" - -#: Template/Users/view.ctp:59;75 -msgid "Created" -msgstr "ŲŖŲ§Ų±ŁŠŲ® Ų§Ł„Ų„ŲŖŲ“Ų§Ų”" - -#: Template/Users/view.ctp:61;76 -msgid "Modified" -msgstr "Ų§Ų®Ų± ŲŖŲ¹ŲÆŁŠŁ„" - -#: View/Helper/UserHelper.php:45 -msgid "Sign in with" -msgstr "ŲÆŲ®ŁˆŁ„ ŲØŲ§Ų³ŲŖŲ®ŲÆŲ§Ł…" - -#: View/Helper/UserHelper.php:48 -msgid "fa fa-{0}" -msgstr "fa fa-{0}" - -#: View/Helper/UserHelper.php:57 -msgid "btn btn-social btn-{0} " -msgstr "btn btn-social btn-{0} " - -#: View/Helper/UserHelper.php:106 -msgid "Logout" -msgstr "ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„Ų®Ų±ŁˆŲ¬" - -#: View/Helper/UserHelper.php:123 -msgid "Welcome, {0}" -msgstr "Ł…Ų±Ų­ŲØŲ§ ŲŒ {0}" - -#: View/Helper/UserHelper.php:146 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" -msgstr "Ł„Ł… ŁŠŲŖŁ… Ų¶ŲØŲ· Ų§Ų¹ŲÆŲ§ŲÆŲ§ŲŖ reCaptcha! Ų§Ł„Ų±Ų¬Ų§Ų” Ų„Ų¶Ų§ŁŲ© Ų§Ų¹ŲÆŲ§ŲÆŲ§ŲŖ Users.reCaptcha.key" - -#: View/Helper/UserHelper.php:205 -msgid "btn btn-social btn-{0}" -msgstr "btn btn-social btn-{0} " - -#: View/Helper/UserHelper.php:211 -msgid "Connected with {0}" -msgstr "Ł…ŲŖŲµŁ„ ŲØ {0}" - -#: View/Helper/UserHelper.php:216 -msgid "Connect with {0}" -msgstr "Ų§Ł„Ų§ŲŖŲµŲ§Ł„ ŲØ {0}" diff --git a/src/Locale/es/Users.mo b/src/Locale/es/Users.mo deleted file mode 100644 index 50edf1e2bd033c310ec6e9f4fe7a3a8d25ed92d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15243 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 diff --git a/src/Locale/es/Users.po b/src/Locale/es/Users.po deleted file mode 100644 index 16f4de825..000000000 --- a/src/Locale/es/Users.po +++ /dev/null @@ -1,854 +0,0 @@ -# LANGUAGE translation of CakePHP Application -# Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com) -# -msgid "" -msgstr "" -"Project-Id-Version: CakeDC Users\n" -"POT-Creation-Date: 2016-10-26 09:23+0000\n" -"PO-Revision-Date: 2017-05-29 16:50+0100\n" -"Last-Translator: Bernat Arlandis \n" -"Language-Team: CakeDC \n" -"Language: es_ES\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.6.10\n" -"X-Poedit-SourceCharset: UTF-8\n" - -#: Auth/ApiKeyAuthenticate.php:73 -msgid "Type {0} is not valid" -msgstr "El tipo {0} no es vĆ”lido" - -#: Auth/ApiKeyAuthenticate.php:77 -msgid "Type {0} has no associated callable" -msgstr "El tipo {0} no tiene un invocable asociado" - -#: Auth/ApiKeyAuthenticate.php:86 -msgid "SSL is required for ApiKey Authentication" -msgstr "SSL requerido para autenticaciĆ³n por ApiKey" - -#: Auth/SimpleRbacAuthorize.php:142 -msgid "" -"Missing configuration file: \"config/{0}.php\". Using default permissions" -msgstr "" -"Falta el archivo de configuraciĆ³n: \"config/{0}.php\". Utilizando permisos " -"predeterminados" - -#: Auth/SocialAuthenticate.php:432 -msgid "Provider cannot be empty" -msgstr "El proveedor no puede ser vacĆ­o" - -#: Auth/Rules/AbstractRule.php:78 -msgid "" -"Table alias is empty, please define a table alias, we could not extract a " -"default table from the request" -msgstr "" -"El alias de la tabla estĆ” vacĆ­o, por favor define un alias para la tabla ya " -"que no podemos establecer una tabla predeterminada de la peticiĆ³n" - -#: Auth/Rules/Owner.php:67;70 -msgid "" -"Missing column {0} in table {1} while checking ownership permissions for " -"user {2}" -msgstr "" -"La columna {0} de la tabla {1} no existe, estĆ”bamos comprobando el permiso " -"de propietario para el usuario {2}" - -#: Controller/SocialAccountsController.php:52 -msgid "Account validated successfully" -msgstr "Cuenta validada correctamente" - -#: Controller/SocialAccountsController.php:54 -msgid "Account could not be validated" -msgstr "No se pudo validar la cuenta" - -#: Controller/SocialAccountsController.php:57 -msgid "Invalid token and/or social account" -msgstr "Token o cuenta social incorrecta" - -#: Controller/SocialAccountsController.php:59;87 -msgid "Social Account already active" -msgstr "Cuenta social ya activa" - -#: Controller/SocialAccountsController.php:61 -msgid "Social Account could not be validated" -msgstr "No se pudo validar la cuenta social " - -#: Controller/SocialAccountsController.php:80 -msgid "Email sent successfully" -msgstr "Email enviado correctamente" - -#: Controller/SocialAccountsController.php:82 -msgid "Email could not be sent" -msgstr "No se puede enviar el email" - -#: Controller/SocialAccountsController.php:85 -msgid "Invalid account" -msgstr "Cuenta invĆ”lida" - -#: Controller/SocialAccountsController.php:89 -msgid "Email could not be resent" -msgstr "No se puede reenviar el Email" - -#: Controller/Component/RememberMeComponent.php:69 -msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" -msgstr "App salt invĆ”lido, debe contener al menos 256 bits (32 bytes)" - -#: Controller/Component/UsersAuthComponent.php:178 -msgid "You can't enable email validation workflow if use_email is false" -msgstr "" -"No es posible activar el flujo de trabajo para la validaciĆ³n de email si " -"use_mail es falso" - -#: Controller/Traits/LoginTrait.php:96 -msgid "Issues trying to log in with your social account" -msgstr "Hubo un problema al iniciar sesiĆ³n con tu cuenta social" - -#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 -msgid "Please enter your email" -msgstr "Por favor, introduce tu email" - -#: Controller/Traits/LoginTrait.php:108 -msgid "" -"Your user has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"El usuario no se ha validado todavĆ­a. Instrucciones enviadas a tu bandeja de " -"entrada" - -#: Controller/Traits/LoginTrait.php:110 -msgid "" -"Your social account has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"La cuenta social no se ha validado todavĆ­a. Instrucciones enviadas a tu " -"bandeja de entrada" - -#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 -msgid "Invalid reCaptcha" -msgstr "El cĆ³digo reCaptcha no es vĆ”lido" - -#: Controller/Traits/LoginTrait.php:171 -msgid "You are already logged in" -msgstr "Ya has iniciado sesiĆ³n" - -#: Controller/Traits/LoginTrait.php:217 -msgid "Username or password is incorrect" -msgstr "Usuario o contraseƱa incorrecta" - -#: Controller/Traits/LoginTrait.php:238 -msgid "You've successfully logged out" -msgstr "SesiĆ³n finalizada correctamente" - -#: Controller/Traits/PasswordManagementTrait.php:47;76 -#: Controller/Traits/ProfileTrait.php:49 -msgid "User was not found" -msgstr "Usuario no encontrado" - -#: Controller/Traits/PasswordManagementTrait.php:64;72;80 -msgid "Password could not be changed" -msgstr "No es posible cambiar la contraseƱa" - -#: Controller/Traits/PasswordManagementTrait.php:68 -msgid "Password has been changed successfully" -msgstr "ContraseƱa cambiada correctamente" - -#: Controller/Traits/PasswordManagementTrait.php:78 -msgid "{0}" -msgstr "{0}" - -#: Controller/Traits/PasswordManagementTrait.php:120 -msgid "Please check your email to continue with password reset process" -msgstr "" -"Por favor, comprueba tu correo para continuar con el proceso de " -"restablecimiento de contraseƱa" - -#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 -msgid "The password token could not be generated. Please try again" -msgstr "" -"No se pudo generar el token de contraseƱa. Por favor, intĆ©ntalo de nuevo" - -#: Controller/Traits/PasswordManagementTrait.php:129 -#: Controller/Traits/UserValidationTrait.php:100 -msgid "User {0} was not found" -msgstr "Usuario {0} no encontrado" - -#: Controller/Traits/PasswordManagementTrait.php:131 -msgid "The user is not active" -msgstr "El usuario no estĆ” activo" - -#: Controller/Traits/PasswordManagementTrait.php:133 -#: Controller/Traits/UserValidationTrait.php:95;104 -msgid "Token could not be reset" -msgstr "No se puede restablecer el token" - -#: Controller/Traits/ProfileTrait.php:53 -msgid "Not authorized, please login first" -msgstr "" -"No estĆ”s autorizado para realizar esta acciĆ³n, por favor inicia sesiĆ³n " -"primero" - -#: Controller/Traits/RegisterTrait.php:42 -msgid "You must log out to register a new user account" -msgstr "Debes finalizar la sesiĆ³n para registrar una nueva cuenta de usuario" - -#: Controller/Traits/RegisterTrait.php:88 -msgid "The user could not be saved" -msgstr "No se ha podido guardar el usuario" - -#: Controller/Traits/RegisterTrait.php:122 -msgid "You have registered successfully, please log in" -msgstr "Registrado correctamente, por favor inicia sesiĆ³n" - -#: Controller/Traits/RegisterTrait.php:124 -msgid "Please validate your account before log in" -msgstr "Por favor, valida tu cuenta antes de iniciar sesiĆ³n" - -#: Controller/Traits/SimpleCrudTrait.php:76;106 -msgid "The {0} has been saved" -msgstr "El {0} ha sido guardado" - -#: Controller/Traits/SimpleCrudTrait.php:80;110 -msgid "The {0} could not be saved" -msgstr "El {0} no ha podido guardarse" - -#: Controller/Traits/SimpleCrudTrait.php:130 -msgid "The {0} has been deleted" -msgstr "El {0} ha sido eliminado" - -#: Controller/Traits/SimpleCrudTrait.php:132 -msgid "The {0} could not be deleted" -msgstr "El {0} no ha podido eliminarse" - -#: Controller/Traits/SocialTrait.php:39 -msgid "The reCaptcha could not be validated" -msgstr "El cĆ³digo reCaptcha no se pudo validar" - -#: Controller/Traits/UserValidationTrait.php:42 -msgid "User account validated successfully" -msgstr "Cuenta de usuario validada correctamente" - -#: Controller/Traits/UserValidationTrait.php:44 -msgid "User account could not be validated" -msgstr "No se pudo validar la cuenta de usuario" - -#: Controller/Traits/UserValidationTrait.php:47 -msgid "User already active" -msgstr "Usuario ya activo" - -#: Controller/Traits/UserValidationTrait.php:53 -msgid "Reset password token was validated successfully" -msgstr "Restablecimiento del token de contraseƱa validado correctamente" - -#: Controller/Traits/UserValidationTrait.php:58 -msgid "Reset password token could not be validated" -msgstr "Restablecimiento del token de contraseƱa no pudo validarse" - -#: Controller/Traits/UserValidationTrait.php:62 -msgid "Invalid validation type" -msgstr "Tipo de validaciĆ³n invĆ”lido" - -#: Controller/Traits/UserValidationTrait.php:65 -msgid "Invalid token or user account already validated" -msgstr "Token invĆ”lido, o tu cuenta ya habĆ­a sido validada anteriormente" - -#: Controller/Traits/UserValidationTrait.php:67 -msgid "Token already expired" -msgstr "Token ya expirado" - -#: Controller/Traits/UserValidationTrait.php:93 -msgid "Token has been reset successfully. Please check your email." -msgstr "" -"Se ha restablecido el token correctamente. Por favor comprueba tu email." - -#: Controller/Traits/UserValidationTrait.php:102 -msgid "User {0} is already active" -msgstr "El usuario {0} ya estĆ” activo" - -#: Email/EmailSender.php:39 -msgid "Your account validation link" -msgstr "Enlace para validar tu cuenta" - -#: Mailer/UsersMailer.php:55 -msgid "{0}Your reset password link" -msgstr "{0} Enlace para restablecer tu contraseƱa" - -#: Mailer/UsersMailer.php:78 -msgid "{0}Your social account validation link" -msgstr "{0} Enlace de validaciĆ³n de tu cuenta social" - -#: Model/Behavior/PasswordBehavior.php:56 -msgid "Reference cannot be null" -msgstr "La referencia no puede estar vacĆ­a" - -#: Model/Behavior/PasswordBehavior.php:61 -msgid "Token expiration cannot be empty" -msgstr "La fecha de expiraciĆ³n del Token no puede estar vacĆ­a" - -#: Model/Behavior/PasswordBehavior.php:67;116 -msgid "User not found" -msgstr "Usuario no encontrado" - -#: Model/Behavior/PasswordBehavior.php:71 -#: Model/Behavior/RegisterBehavior.php:111 -msgid "User account already validated" -msgstr "Tu usuario ya se habĆ­a validado antes" - -#: Model/Behavior/PasswordBehavior.php:78 -msgid "User not active" -msgstr "El usuario no estĆ” activo" - -#: Model/Behavior/PasswordBehavior.php:121 -msgid "The current password does not match" -msgstr "La contraseƱa actual no coincide" - -#: Model/Behavior/PasswordBehavior.php:124 -msgid "You cannot use the current password as the new one" -msgstr "No puedes usar tu contraseƱa actual como nueva contraseƱa" - -#: Model/Behavior/RegisterBehavior.php:89 -msgid "User not found for the given token and email." -msgstr "Usuario no encontrado para el token y email proporcionado" - -#: Model/Behavior/RegisterBehavior.php:92 -msgid "Token has already expired user with no token" -msgstr "El token ha expirado usuario sin token" - -#: Model/Behavior/SocialAccountBehavior.php:102;129 -msgid "Account already validated" -msgstr "Cuenta ya activada" - -#: Model/Behavior/SocialAccountBehavior.php:105;132 -msgid "Account not found for the given token and email." -msgstr "Cuenta no encontrada para el token y email proporcionado" - -#: Model/Behavior/SocialBehavior.php:56 -msgid "Unable to login user with reference {0}" -msgstr "No se puede iniciar sesiĆ³n con el usuario con referencia {0}" - -#: Model/Behavior/SocialBehavior.php:98 -msgid "Email not present" -msgstr "No se encuentra el email" - -#: Model/Table/UsersTable.php:82 -msgid "Your password does not match your confirm password. Please try again" -msgstr "" -"La contraseƱa y la comprobaciĆ³n no concuerdan. Por favor intĆ©ntalo de nuevo" - -#: Model/Table/UsersTable.php:175 -msgid "Username already exists" -msgstr "Nombre de usuario ya existente" - -#: Model/Table/UsersTable.php:181 -msgid "Email already exists" -msgstr "Email ya existente" - -#: Model/Table/UsersTable.php:214 -msgid "Missing 'username' in options data" -msgstr "Falta 'username' en las opciones" - -#: Shell/UsersShell.php:54 -msgid "Utilities for CakeDC Users Plugin" -msgstr "Utilidades para CakeDC Users Plugin" - -#: Shell/UsersShell.php:55 -msgid "Activate an specific user" -msgstr "Activar un usuario especĆ­fico" - -#: Shell/UsersShell.php:56 -msgid "Add a new superadmin user for testing purposes" -msgstr "AƱadir un nuevo superadmin" - -#: Shell/UsersShell.php:57 -msgid "Add a new user" -msgstr "AƱadir un nuevo usuario" - -#: Shell/UsersShell.php:58 -msgid "Change the role for an specific user" -msgstr "Cambiar el rol de un usuario especĆ­fico" - -#: Shell/UsersShell.php:59 -msgid "Deactivate an specific user" -msgstr "Desactivar un usuario" - -#: Shell/UsersShell.php:60 -msgid "Delete an specific user" -msgstr "Borrar un usuario" - -#: Shell/UsersShell.php:61 -msgid "Reset the password via email" -msgstr "Restablecer la contraseƱa vĆ­a email" - -#: Shell/UsersShell.php:62 -msgid "Reset the password for all users" -msgstr "Restablecer la contraseƱa de todos los usuarios" - -#: Shell/UsersShell.php:63 -msgid "Reset the password for an specific user" -msgstr "Restablecer la contraseƱa de un usuario concreto" - -#: Shell/UsersShell.php:98 -msgid "User added:" -msgstr "Usuario aƱadido:" - -#: Shell/UsersShell.php:99;127 -msgid "Id: {0}" -msgstr "Id: {0}" - -#: Shell/UsersShell.php:100;128 -msgid "Username: {0}" -msgstr "Nombre de usuario: {0}" - -#: Shell/UsersShell.php:101;129 -msgid "Email: {0}" -msgstr "Email: {0}" - -#: Shell/UsersShell.php:102;130 -msgid "Password: {0}" -msgstr "ContraseƱa: {0}" - -#: Shell/UsersShell.php:126 -msgid "Superuser added:" -msgstr "Superusuario aƱadido:" - -#: Shell/UsersShell.php:132 -msgid "Superuser could not be added:" -msgstr "No se pudo aƱadir un superusuario:" - -#: Shell/UsersShell.php:135 -msgid "Field: {0} Error: {1}" -msgstr "Campo: {0} Error: {1}" - -#: Shell/UsersShell.php:153;179 -msgid "Please enter a password." -msgstr "Por favor, introduce una contraseƱa." - -#: Shell/UsersShell.php:157 -msgid "Password changed for all users" -msgstr "ContraseƱa cambiada para todos los usuarios" - -#: Shell/UsersShell.php:158;186 -msgid "New password: {0}" -msgstr "Nueva contraseƱa: {0}" - -#: Shell/UsersShell.php:176;204;282;324 -msgid "Please enter a username." -msgstr "Por favor introduce el nombre de usuario." - -#: Shell/UsersShell.php:185 -msgid "Password changed for user: {0}" -msgstr "ContraseƱa cambiada para el usuario: {0}" - -#: Shell/UsersShell.php:207 -msgid "Please enter a role." -msgstr "Por favor introduce el rol." - -#: Shell/UsersShell.php:213 -msgid "Role changed for user: {0}" -msgstr "Rol cambiado para el usuario: {0}" - -#: Shell/UsersShell.php:214 -msgid "New role: {0}" -msgstr "Nuevo rol: {0}" - -#: Shell/UsersShell.php:229 -msgid "User was activated: {0}" -msgstr "Usuario activado: {0}" - -#: Shell/UsersShell.php:244 -msgid "User was de-activated: {0}" -msgstr "Usuario desactivado: {0}" - -#: Shell/UsersShell.php:256 -msgid "Please enter a username or email." -msgstr "Por favor introduce el nombre de usuario o email." - -#: Shell/UsersShell.php:264 -msgid "" -"Please ask the user to check the email to continue with password reset " -"process" -msgstr "" -"Por favor, pide al usuario que mire su buzĆ³n de correo para continuar con el " -"proceso de restablecimiento de su contraseƱa" - -#: Shell/UsersShell.php:302 -msgid "The user was not found." -msgstr "Usuario no encontrado." - -#: Shell/UsersShell.php:332 -msgid "The user {0} was not deleted. Please try again" -msgstr "El usuario {0} no ha sido borrado. IntĆ©ntalo de nuevo por favor" - -#: Shell/UsersShell.php:334 -msgid "The user {0} was deleted successfully" -msgstr "El usuario {0} se borrĆ³ correctamente" - -#: Template/Email/html/reset_password.ctp:21 -#: Template/Email/html/social_account_validation.ctp:14 -#: Template/Email/html/validation.ctp:21 -#: Template/Email/text/reset_password.ctp:20 -#: Template/Email/text/social_account_validation.ctp:22 -#: Template/Email/text/validation.ctp:20 -msgid "Hi {0}" -msgstr "Hola {0}" - -#: Template/Email/html/reset_password.ctp:24 -msgid "Reset your password here" -msgstr "Restablece tu contraseƱa aquĆ­" - -#: Template/Email/html/reset_password.ctp:27 -#: Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 -msgid "" -"If the link is not correcly displayed, please copy the following address in " -"your web browser {0}" -msgstr "" -"Por favor, copia la siguiente direcciĆ³n en tu navegador si el enlace no se " -"ve correctamente {0}" - -#: Template/Email/html/reset_password.ctp:30 -#: Template/Email/html/social_account_validation.ctp:35 -#: Template/Email/html/validation.ctp:30 -#: Template/Email/text/reset_password.ctp:24 -#: Template/Email/text/social_account_validation.ctp:26 -#: Template/Email/text/validation.ctp:24 -msgid "Thank you" -msgstr "Gracias" - -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" -msgstr "Activa tu acceso social aquĆ­" - -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" -msgstr "Activa tu cuenta aquĆ­" - -#: Template/Email/text/reset_password.ctp:22 -#: Template/Email/text/validation.ctp:22 -msgid "Please copy the following address in your web browser {0}" -msgstr "Por favor copia la siguiente direcciĆ³n en tu navegador {0}" - -#: Template/Email/text/social_account_validation.ctp:24 -msgid "" -"Please copy the following address in your web browser to activate your " -"social login {0}" -msgstr "" -"Por favor copia la siguiente direcciĆ³n en tu navegador para activar tu " -"acceso social {0}" - -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 -msgid "Actions" -msgstr "Acciones" - -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 -#: Template/Users/view.ctp:19 -msgid "List Users" -msgstr "Listar Usuarios" - -#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:21 -msgid "List Accounts" -msgstr "Listar Cuentas" - -#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 -msgid "Add User" -msgstr "AƱadir Usuario" - -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 -#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 -#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 -msgid "Username" -msgstr "Usuario" - -#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 -#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 -msgid "Email" -msgstr "Email" - -#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 -msgid "First name" -msgstr "Nombre" - -#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 -msgid "Last name" -msgstr "Apellidos" - -#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:44;75 -msgid "Active" -msgstr "Activo" - -#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 -#: Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:19 -msgid "Submit" -msgstr "Enviar" - -#: Template/Users/change_password.ctp:5 -msgid "Please enter the new password" -msgstr "Por favor introduce la nueva contraseƱa" - -#: Template/Users/change_password.ctp:10 -msgid "Current password" -msgstr "ContraseƱa actual" - -#: Template/Users/change_password.ctp:16 -msgid "New password" -msgstr "Nueva contraseƱa" - -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 -msgid "Confirm password" -msgstr "Confirmar contraseƱa" - -#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:101 -msgid "Delete" -msgstr "Eliminar" - -#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:18;101 -msgid "Are you sure you want to delete # {0}?" -msgstr "ĀæEstĆ” seguro de que quieres eliminar # {0}?" - -#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 -msgid "Edit User" -msgstr "Editar Usuario" - -#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 -msgid "Token" -msgstr "Token" - -#: Template/Users/edit.ctp:41 -msgid "Token expires" -msgstr "Token caduca" - -#: Template/Users/edit.ctp:44 -msgid "API token" -msgstr "Api Token" - -#: Template/Users/edit.ctp:47 -msgid "Activation date" -msgstr "Fecha de activaciĆ³n" - -#: Template/Users/edit.ctp:50 -msgid "TOS date" -msgstr "Fecha TOS" - -#: Template/Users/index.ctp:15 -msgid "New {0}" -msgstr "Nuevo {0}" - -#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 -msgid "View" -msgstr "Ver" - -#: Template/Users/index.ctp:38 -msgid "Change password" -msgstr "Cambiar contraseƱa" - -#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 -msgid "Edit" -msgstr "Editar" - -#: Template/Users/index.ctp:49 -msgid "previous" -msgstr "anterior" - -#: Template/Users/index.ctp:51 -msgid "next" -msgstr "siguiente" - -#: Template/Users/login.ctp:19 -msgid "Please enter your username and password" -msgstr "Por favor introduce tu usuario y contraseƱa" - -#: Template/Users/login.ctp:29 -msgid "Remember me" -msgstr "RecuĆ©rdame" - -#: Template/Users/login.ctp:37 -msgid "Register" -msgstr "Registrarse" - -#: Template/Users/login.ctp:43 -msgid "Reset Password" -msgstr "Cambiar contraseƱa" - -#: Template/Users/login.ctp:48 -msgid "Login" -msgstr "Iniciar sesiĆ³n" - -#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 -msgid "{0} {1}" -msgstr "{0} {1}" - -#: Template/Users/profile.ctp:24 -msgid "Change Password" -msgstr "Cambiar contraseƱa" - -#: Template/Users/profile.ctp:34 -msgid "Social Accounts" -msgstr "Cuentas sociales" - -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 -msgid "Avatar" -msgstr "Avatar" - -#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 -msgid "Provider" -msgstr "Proveedor" - -#: Template/Users/profile.ctp:40 -msgid "Link" -msgstr "Enlace" - -#: Template/Users/profile.ctp:47 -msgid "Link to {0}" -msgstr "Enlace a {0}" - -#: Template/Users/register.ctp:20 -msgid "Password" -msgstr "ContraseƱa" - -#: Template/Users/register.ctp:28 -msgid "Accept TOS conditions?" -msgstr "ĀæAceptas las condiciones del servicios?" - -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" -msgstr "Por favor introduce tu email para restablecer tu contraseƱa" - -#: Template/Users/resend_token_validation.ctp:15 -msgid "Resend Validation email" -msgstr "Reenviar email de validaciĆ³n" - -#: Template/Users/resend_token_validation.ctp:17 -msgid "Email or username" -msgstr "Email o usuario" - -#: Template/Users/view.ctp:18 -msgid "Delete User" -msgstr "Eliminar Usuario" - -#: Template/Users/view.ctp:20 -msgid "New User" -msgstr "Nuevo Usuario" - -#: Template/Users/view.ctp:28;67 -msgid "Id" -msgstr "Id" - -#: Template/Users/view.ctp:34 -msgid "First Name" -msgstr "Nombre" - -#: Template/Users/view.ctp:36 -msgid "Last Name" -msgstr "Apellidos" - -#: Template/Users/view.ctp:40 -msgid "Api Token" -msgstr "Api Token" - -#: Template/Users/view.ctp:48;74 -msgid "Token Expires" -msgstr "Token caduca" - -#: Template/Users/view.ctp:50 -msgid "Activation Date" -msgstr "Fecha de activaciĆ³n" - -#: Template/Users/view.ctp:52 -msgid "Tos Date" -msgstr "Fecha Tos" - -#: Template/Users/view.ctp:54;77 -msgid "Created" -msgstr "Creado" - -#: Template/Users/view.ctp:56;78 -msgid "Modified" -msgstr "Modificado" - -#: Template/Users/view.ctp:63 -msgid "Related Accounts" -msgstr "Cuentas relacionadas" - -#: Template/Users/view.ctp:68 -msgid "User Id" -msgstr "Id Usuario" - -#: Template/Users/view.ctp:71 -msgid "Reference" -msgstr "Referencia" - -#: Template/Users/view.ctp:76 -msgid "Data" -msgstr "Datos" - -#: View/Helper/UserHelper.php:46 -msgid "Sign in with" -msgstr "Iniciar sesiĆ³n con" - -#: View/Helper/UserHelper.php:49 -msgid "fa fa-{0}" -msgstr "fa fa-{0}" - -#: View/Helper/UserHelper.php:52 -msgid "btn btn-social btn-{0} " -msgstr "btn btn-social btn-{0}" - -#: View/Helper/UserHelper.php:91 -msgid "Logout" -msgstr "Salir" - -#: View/Helper/UserHelper.php:108 -msgid "Welcome, {0}" -msgstr "Bienvenido/a, {0}" - -#: View/Helper/UserHelper.php:131 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" -msgstr "" -"reCaptcha no se ha configurado, por favor configura Users.reCaptcha.key" - -#: Model/Behavior/RegisterBehavior.php:148 -msgid "This field is required" -msgstr "Este campo es requerido" - -#~ msgid "The old password does not match" -#~ msgstr "La antigua contraseƱa no coincide" - -#~ msgid "SocialAccount already active" -#~ msgstr "Cuenta social ya activa" - -#~ msgid "" -#~ "The social account is not active. Please check your email for " -#~ "instructions. {0}" -#~ msgstr "" -#~ "La cuenta social estĆ” inactiva. Por favor, compruebe las instrucciones en " -#~ "su correo. {0}" - -#~ msgid "There was an error associating your social network account" -#~ msgstr "Hubo un error al asociar su cuenta de la red social" - -#~ msgid "Invalid token and/or email" -#~ msgstr "Token y/o email invĆ”lido" - -#~ msgid "The \"tos\" property is not present" -#~ msgstr "La propiedad \"tos\" no estĆ” presente" - -#~ msgid "+ {0} secs" -#~ msgstr "+ {0} secs" - -#~ msgid "Sign in with Facebook" -#~ msgstr "Login con Facebook" - -#~ msgid "Sign in with Twitter" -#~ msgstr "Login con Twitter" diff --git a/src/Locale/fr_FR/Users.mo b/src/Locale/fr_FR/Users.mo deleted file mode 100644 index fc623371daeb2249909fa3fc2f7b26a62cfd7179..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16147 zcmchd3y>vMdB=~4hzp1!iUMl$(Am|U*`4L-EXXdiyST8sF0&6%5$L(MXQp@W?Y?y1 zJF~+IzM_CZqk{MrqCuF|C?Y;ejb+tXCXrGTtdy}5lPaHOOpJMyF-0oo_dn-!-|joJ zi>Q@bd*tvn)iFb)4)TZ*8Li&t$qVM z1^h0ke*Xq)-Cu&R#F&$eIT<(x)V@vw)&D$@E@r#O>wNtU;0o$*1D^@r>E91|{0yk| zzXBcw{y8XmzYbmxJ_2fg=RCuhP2f1Fb#4XE0^bL&0ly52j-P{T!DAp&bYI|cBdGmc z0cxK+!4tr1K+(4k)c$&)=s5_U3BCcm61*3@4E!%p^0|b~2ww&s4_*n1u4_Tf+X1zY zn?cREbXKv{4+n}kM!w@3>pI0fiD7I35u>af&4RXb`gttM@M7>3Q1TcD126}*-kqTA>PsL)%y&WA!@q;8z!P{8A1?q!_a^WK z;3O#d-wH}D?*T=}-JtqC0E)hEf-~TEK+(Se<(7V24z33i@NDo9$UpNf{=iD}Gf?|D z3gWchsi63@0TjI{f0)wT4vOykK#lu~$M1mBo1cS{+kb+H(i{bG>i=vo07pT!Pk^hz z>%sNlTS3wPm!Rl<1l0Ing5ulpD2w#yTu^#*5r5S0RUTgpN**5pQGN4CQ2bg1C6{l5 z!{GNp?el3kAMIx)h-sN||GpR0zHR_T&#j>PzXOzBEr6o`VgLSJQ1IvreR#jehe1d&kAkquoXX^~>kGiE!PkI0z`p^t{@EChy$_UpKMcyAz6{>{1Y>>#icd|HK>O~1;`19pn#_Aa$>U3)#{CM^e9uQI z)IJ1Co|l6w!3L;#ZufXM_$1yR1jWbCgWJGwfr!$a&ZJs@43vM`0!mJEp!Ru-$Gbtv z>vN#^`6E#K|1~K2J_V)F{+|m{WnKuXeLJXmt^y(5q@eoU35uQ%`uB%G&HHB{|IByz zqyE1J#gDVuoai0%cr_?JngzB0H-S$EKjiVFp!W3%k6!@g2fqfkz`q5x&&{jYBe(|? zKfecRpK?Oy03)E}HVIx2-V92v|LE}t;L*JQ1k`%}42u810=4hsUhMSnEKuvM1*LZz zzyn|hd^Pw}@Hp_Y)o%PQQ2uiYlwBMI#pk;~^*aP=p3j2EgFp7~{{f2rv-ran&6OZk z=0;F--3PuN`~uhjFT$zp1MdMhfX6Xu0B!>%k2ZKNcngTim@k2d#C#tVT`N$UOTia_ z7lSk4`QS%E(fK`4<9_PjPaJjnaT>US`b)tR!0n*udle|TC!p-{4sZ+jAb2_W-{1w{ zrgg@=6nqT`>&zEHt@9I5`ga1tLzL!R@af>SpxQg2_H!3_BKR;Uz4<#(a{d9x*37TL zW5G3aeiL{h_$2Vlp!oV#@MYk?fSULG^W3?04JbXm1=K$71=+g!Iw*P{1o#TQR=? zwa(cWIyqeop2GVAg z&lTXhi=4b~1~vcv;5FdG;H}_FlyesR6sYx9B8;bi8$ikba!~p@0ZOjdg0l1beEY{h zRLguC6yJXgJ^>VuK0|qkaw?_xZRFuvN?ufW6pyc_+(kLw*9ksBk)B^q`6CMM!|Kbs zK*{HI6#Zml`n{LJ5ocqLonSzbo~D!?l&dKE{i%cUFJiHJa$Q-2Zu5LH<#WDn%Hzku zkN9Wl+`B0!Q4aaK1}NUje)mx>q3G9jQ2UFSSb0fS`n`d&)jm1D^ZQvB}V z;eN^kzT$bH^g+Krq`Z?dLD@jrM0q3SD9Sr1(hL1$Zz1J&%5x~&Df*pFc{N4)b{0i` z=4i@Il;U>*51*ne6cymdD$g0uucUmIa!jSZ&GVI%=TZ*(`ZK|4%7c{8Q=UypD4(XR zpvZ6O_cqG06imgupCZ5W9?DxN#cz^_4h8eH=cVda`vWlYLC-rCJ&aFW=-5(`pW1|suy20+3?+O}e z(u})tn&g+LI_)LhAZ%q(*qje$!&cl3yHT@jp}o}%lC&F4M$0s-VTvi5{LO;yOcYGV zvr*z!4MOUpb{Mxt%K6F_g1iS!c|O%^wdQHI6j_{w0EPy6Cu+n~aUt^mCqcEHEeD&JyXdcXZPvX5&1SI2F2zF_B+(o+cA_k7wwXyp zxJ^cRH%_L5PA}`Ed6e66uDc_&69>B;)3YdmT4wPNb0NI$ra?1mMeOmc;NaSu5CR(x zGc!IDCeu-{GtBe3G;0>`oq>1pI7?fRrDX}1#?xdf&e}nL6oQpJ$9q{8v3l76CqlC+ z3Ss>64Buplq>H81GR8kIS#>iCW%S4KZ?i;h?B7zeq62Z>&3$D}sj?`Cu;p4R_0qFW zttaXxb|+yw@?+J#u2q(VF>%>!iKAB2J_eh!EX{ZvRc)4cgB_Z~J=*DB7TY0Pn`WyU zVzy3M-EPIn{vgh+IW$rj+Gx!O%{cG0!uhDVI_R{bFpsdX&b;kEm9|>xoRlSOHlaQb zP$a9rbJ1ilnWb}5Dv`G}v4&CTb^pE73G%SjT^)q}DQNc~8Dk8)ftKqA>&`nrn2fu5 zu=1RB!Q^~5%2%QN$#gkM7LA9UZeu1aYphd{d9Hzt-e9~*4fOGBE(j~-S=w>g-`B{h zy7QgLY|Zmtln32xUJO9%u}JNIF7D1aCJZdRO`EZ@uuoPL+u*p-A59=eZ9|O$@3wOH zCe`Fo_O8EauWPo)d9GE53KbdB%4x?s85w<8c4?%oUOUm;>e3A-F)dUhn45`tYRp89 z{hBGAOIT$l?gV&*wx-8{S{u|7!NGMmRc6Enr+Znb)q*Le84J$D>r%OfWkxzPoij(U z6iwTVrovte-R@6nwx> z`9+*W-ZeW5-%>oVUpXP?&BIp9npj@;t2JxiZpHrS>S5uh>JOd?bM%(Op;)AL0u+<@ zDV-&SIfBRGSstSSRvfm*9xGA`7>hgZMNY3een)|PgCT&pXo~0|X+-^}N}q(dgobJS4U5Y~MKysMvb5e$u)A5>Gk50hKcn#a=vWGGbsyR*A|p zA4eW19LoL#vAtFYa|#9u0Y?YA8T8Yq@cQnwnaa|(^=aY}!KK-a6Si)OCngw(+=6Dx zu_{e&haBp*Pbu_elxjNSR%p+|S&pc( z%|}IEK4rC3R;1cH!brb6E-X-+i-ZT1xg1^e(hR=mVK$+jHS&CSyW*0@KJ98M&!xdJ zWkb=QO>!`EAF3#{ak0Mr8*Dz%LCJGhS1N5}Yhl(>i>Gshz-@!==7NSnS5@gy&MxYT zdz)XuiOB|7N$MPopS#?OU9jdmN{+h2weQ3cSDL#U({2Jf8zN~QrskBDeaa&?@G&wB zQ}*$yU_F)DlUS?4@4LXmDw3rzE8MS*>-H#$BI34Kc=Td>rPHf7*93l;K4o=n&wd_f z{%%Qs1NI7R>!fyr?^coB@KUecwGb;g%-z>cCT+KqiEA#%DeIfj@Zp-uMckUwSNK~n zrb?ZfYUXA~*eF^H+4H^_=WkdG#+S@ z9M{rQ{Jl4h=FC-5tC6;&)mE^t-~t?SEEh|o1`06gs}>Y}s2fC1NnA|kC8lGPd+`1# zZcsryCDp#pb%4OBu$4!}1Y!}b)`c!{mT$zg)KbO_+@*7OUyVdAj8&NT-djGkJI_Z z1+z`zm~BXg?45}uUa)wmi+i%-rHdb!FnKpid$TaMBcmn0-Dj61qF1a-T}CKCl5%lD zS<1x)QV`|zVX(N+WvHJuz~eNmQ&_y8d|@@$3DrH4i*l?vI>JiDjKqSr>uhvmFq?`- zPkY>m2O7BN5JrKX3&RQKUo)_K((T4+W^v@anWy5pDjLwkefqC5Dn&_Osmzp zpgw=LxPa^liMCgk)#2ZZT4qz4B#R4CZZ@GZRxC?6UQ+>XE81w3>6+r6g4R$)0+sqB zkn595S&?0WEwxF;y+S)B_R4L;gu;qyElcc&Jx9rGI$v0spJ7SAqEoRR(PVQ7LEdrrZ_F^jk5fXflL0OP?@G<$=4T1Lzk{VT3b_3#)_Ks28_dm@diSSV}S! z+6=H_0}}4IQZAJkhO_J>oQP1TKRaCn`|&1T~AEe>9h)?FFLLc zT4B(5jLyw8?hZT0CnZnkz0FV1$)%{ zpuUpyE~vn8mdSj3la~HyQs3vQ&b{{H5@FD7xz^PICc)L@UmaZU zUvtZzbOMX&F7ZAC(Th#JIoDh3Si~W|z3wn;G&p|jExcBft5!nxRH|L4NE~s>Lo1&@ zk-YQS2vTlTf8^qbS5Q8bsIj=v)CW*!NVu0SpJ%iHE7TdijQN`_=y$^RKMqSpMC5~tSCS0)GI9h83;eAD)i4wIGnCnWY2fr^U&ZS( zBlOvU{Pqw*b0Z^{=;Hufh`nNPRODiGf+}E8?KIZ(HXd?fC?sh~$Ii%HE9R$Dm6^z^ z#z{8fZa2S)kuG&V#pUVoO;b3hWiLrbCRn>$-myN$IBUH}2$LUcILA}L;W|%?J6e^k z_5wCxuM&j=w(Hj&s*f%COrl`Lekbv+^e~@EDxrgQ=tZdLWLJ%`{PkDfYRZN0?p8b) z(i~o*E(+xarl75Nz-(5GAKAMIx4z1e7KFMya_Eg|A#P^_%}b7~et&yK<=Sqx4WY2u zj)ZH27BNI0@hYdWf&(LJI)p9{(r!hh-L_v(~(0+8mj_`8Dtd$spr8+$lN}N<; zJVwiEKK&buSBHUC7g4xy&u2bH2BuJaSs1OqeVR=v;Q)Xw%VPg04J*pdbeU^|~3@#fgW5yAzy)pKU(A`Xo{ib8R zsG=1s>%P$WmgiDT_6v-Qz??c1`!4r@s7n`YrBnIdQ%t^bAAiut(jM(Dga zSdJ0P%j?_LHvg+GkM-Yh`nNNkZ8d$hN++wW9H!_+?b2S+{=!98stUoChE?X*s-2cd zvFPp`V~y3msm4dMr=P#5xX5a4%}G}qlo_#sCfYJs?=AFj^)7;fg-#cbl(Vd})#ok! zvc>gd**?(i@>g>D80D)6yhXvfnoAkzBU6_2Ydm-?A5!d{dpIi6>oZtNwM_J<|9NO{ z*rbA&??Mm^uWJ6@>16R4Y{^odGgd6!P~Ut@mb))uwQm7tFDXlNDft2-x1RqnwpXW> zP8<$A=R=Bn1oF0x{wO1fq?63b#07b}RdH-E9@DaF=lqjSwjw+U^0@NN%rjX>r>=DF z``I#!IBvRCYW!ezoqt5fWL1`p_3Qh|N$+!G;nSY`(uSc{PVrgoz1S{ipB>wbT&i2! zs-#04W6ODyhR^8_F>U`wQO$=e`Qscyu5WwD% z$+@|Nus=Ul&jDB!c m)S@zb^pX0=9|Ro}3T\n" -"Language-Team: CakeDC \n" -"Language: fr_FR\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 1.8.11\n" - -#: Auth/ApiKeyAuthenticate.php:73 -msgid "Type {0} is not valid" -msgstr "Le type {0} est invalide" - -#: Auth/ApiKeyAuthenticate.php:77 -msgid "Type {0} has no associated callable" -msgstr "Le type {0} n'a aucune fonction de rappel associĆ©e" - -#: Auth/ApiKeyAuthenticate.php:86 -msgid "SSL is required for ApiKey Authentication" -msgstr "SSL est requis pour ApiKey Authentication" - -#: Auth/SimpleRbacAuthorize.php:142 -msgid "" -"Missing configuration file: \"config/{0}.php\". Using default permissions" -msgstr "" -"Fichier de configuration manquant : \"config/{0}.php\". Utilisation des " -"permissions par dĆ©faut" - -#: Auth/SocialAuthenticate.php:432 -msgid "Provider cannot be empty" -msgstr "Le fournisseur ne peut pas ĆŖtre vide" - -#: Auth/Rules/AbstractRule.php:78 -msgid "" -"Table alias is empty, please define a table alias, we could not extract a " -"default table from the request" -msgstr "" -"L'alias de table est vide, merci de dĆ©finir un alias de table, nous ne " -"pouvons pas extraire une table par dĆ©faut depuis la requĆŖte" - -#: Auth/Rules/Owner.php:67;70 -msgid "" -"Missing column {0} in table {1} while checking ownership permissions for " -"user {2}" -msgstr "" -"Colonne {0} manquante dans la table {1} lors de la vĆ©rification des " -"autorisations de propriĆ©tĆ© pour l'utilisateur {2}" - -#: Controller/SocialAccountsController.php:52 -msgid "Account validated successfully" -msgstr "Le compte a Ć©tĆ© validĆ© avec succĆØs" - -#: Controller/SocialAccountsController.php:54 -msgid "Account could not be validated" -msgstr "Le compte n'a pas pu ĆŖtre validĆ©" - -#: Controller/SocialAccountsController.php:57 -msgid "Invalid token and/or social account" -msgstr "Jeton et/ou compte de rĆ©seau social invalide" - -#: Controller/SocialAccountsController.php:59;87 -msgid "Social Account already active" -msgstr "Compte de rĆ©seau social dĆ©jĆ  actif" - -#: Controller/SocialAccountsController.php:61 -msgid "Social Account could not be validated" -msgstr "Le compte de rĆ©seau social n'a pas pu ĆŖtre validĆ©" - -#: Controller/SocialAccountsController.php:80 -msgid "Email sent successfully" -msgstr "Courriel envoyĆ© avec succĆØs" - -#: Controller/SocialAccountsController.php:82 -msgid "Email could not be sent" -msgstr "Le courriel n'a pas pu ĆŖtre envoyĆ©" - -#: Controller/SocialAccountsController.php:85 -msgid "Invalid account" -msgstr "Compte invalide" - -#: Controller/SocialAccountsController.php:89 -msgid "Email could not be resent" -msgstr "Le courriel n'a pas pu ĆŖtre rĆ©envoyĆ©" - -#: Controller/Component/RememberMeComponent.php:69 -msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" -msgstr "" -"ClĆ© de salage de l'application invalide, la clĆ© de salage de l'application " -"doit-ĆŖtre d'une longueur minimale de 256 bits (32 octets)" - -#: Controller/Component/UsersAuthComponent.php:178 -msgid "You can't enable email validation workflow if use_email is false" -msgstr "" -"Vous ne pouvez pas activer le processus de validation par courriel si " -"use_email est dĆ©fini Ć  false" - -#: Controller/Traits/LoginTrait.php:96 -msgid "Issues trying to log in with your social account" -msgstr "" -"Un problĆØme est survu lors de la tentative d'identification avec votre " -"compte de rĆ©seau social" - -#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 -msgid "Please enter your email" -msgstr "Merci d'entrer votre email" - -#: Controller/Traits/LoginTrait.php:108 -msgid "" -"Your user has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Votre compte n'a pas encore Ć©tĆ© validĆ©. Merci de vĆ©rifier votre boĆ®te de " -"rĆ©ception pour obtenir les instructions" - -#: Controller/Traits/LoginTrait.php:110 -msgid "" -"Your social account has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Votre compte de rĆ©seau social n'a pas encore Ć©tĆ© validĆ©. Merci de vĆ©rifier " -"votre boĆ®te de rĆ©ception pour obtenir les instructions" - -#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 -msgid "Invalid reCaptcha" -msgstr "La validation reCaptcha a Ć©chouĆ©" - -#: Controller/Traits/LoginTrait.php:171 -msgid "You are already logged in" -msgstr "Vous ĆŖtes dĆ©jĆ  identifiĆ©" - -#: Controller/Traits/LoginTrait.php:217 -msgid "Username or password is incorrect" -msgstr "Le nom d'utilisateur ou le mot de passe est incorrect" - -#: Controller/Traits/LoginTrait.php:238 -msgid "You've successfully logged out" -msgstr "Vous avez Ć©tĆ© correctement dĆ©connectĆ©" - -#: Controller/Traits/PasswordManagementTrait.php:47;76 -#: Controller/Traits/ProfileTrait.php:49 -msgid "User was not found" -msgstr "L'utilisateur n'a pas Ć©tĆ© trouvĆ©" - -#: Controller/Traits/PasswordManagementTrait.php:64;72;80 -msgid "Password could not be changed" -msgstr "Le mot de passe n'a pas pu ĆŖtre changĆ©" - -#: Controller/Traits/PasswordManagementTrait.php:68 -msgid "Password has been changed successfully" -msgstr "Le mot de passe a Ć©tĆ© changĆ© avec succĆØs" - -#: Controller/Traits/PasswordManagementTrait.php:78 -msgid "{0}" -msgstr "{0}" - -#: Controller/Traits/PasswordManagementTrait.php:120 -msgid "Please check your email to continue with password reset process" -msgstr "" -"Merci de vĆ©rifier vos courriels pour poursuivre la procĆ©dure de " -"rĆ©initialisation du mot de passe" - -#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 -msgid "The password token could not be generated. Please try again" -msgstr "Le jeton du mot de passe n'a pas pu ĆŖtre gĆ©nĆ©rĆ©. Veuillez rĆ©essayer" - -#: Controller/Traits/PasswordManagementTrait.php:129 -#: Controller/Traits/UserValidationTrait.php:100 -msgid "User {0} was not found" -msgstr "L'utilisateur {0} n'a pas Ć©tĆ© trouvĆ©" - -#: Controller/Traits/PasswordManagementTrait.php:131 -msgid "The user is not active" -msgstr "L'utilisateur n'est pas actif" - -#: Controller/Traits/PasswordManagementTrait.php:133 -#: Controller/Traits/UserValidationTrait.php:95;104 -msgid "Token could not be reset" -msgstr "Le jeton n'a pas pu ĆŖtre rĆ©initialisĆ©" - -#: Controller/Traits/ProfileTrait.php:53 -msgid "Not authorized, please login first" -msgstr "Non autorisĆ©, merci de vous identifier d'abord" - -#: Controller/Traits/RegisterTrait.php:42 -msgid "You must log out to register a new user account" -msgstr "" -"Vous devez vous dĆ©connecter pour enregistrer un nouveau compte utilisateur" - -#: Controller/Traits/RegisterTrait.php:88 -msgid "The user could not be saved" -msgstr "L'utilisateur n'a pas pu ĆŖtre sauvegardĆ©" - -#: Controller/Traits/RegisterTrait.php:122 -msgid "You have registered successfully, please log in" -msgstr "Vous ĆŖtes dĆ©sormais enregistrĆ©, merci de vous identifier" - -#: Controller/Traits/RegisterTrait.php:124 -msgid "Please validate your account before log in" -msgstr "Merci de valider votre compte avant de vous identifier" - -#: Controller/Traits/SimpleCrudTrait.php:76;106 -msgid "The {0} has been saved" -msgstr "Le {0} a Ć©tĆ© sauvegardĆ©" - -#: Controller/Traits/SimpleCrudTrait.php:80;110 -msgid "The {0} could not be saved" -msgstr "Le {0} n'a pas pu ĆŖtre sauvegardĆ©" - -#: Controller/Traits/SimpleCrudTrait.php:130 -msgid "The {0} has been deleted" -msgstr "Le {0} a Ć©tĆ© supprimĆ©" - -#: Controller/Traits/SimpleCrudTrait.php:132 -msgid "The {0} could not be deleted" -msgstr "Le {0} n'a pas pu ĆŖtre supprimĆ©" - -#: Controller/Traits/SocialTrait.php:39 -msgid "The reCaptcha could not be validated" -msgstr "Le reCaptcha n'a pas pu ĆŖtre validĆ©" - -#: Controller/Traits/UserValidationTrait.php:42 -msgid "User account validated successfully" -msgstr "Compte utilisateur validĆ© avec succĆØs" - -#: Controller/Traits/UserValidationTrait.php:44 -msgid "User account could not be validated" -msgstr "Le compte utilisateur n'a pas pu ĆŖtre validĆ©" - -#: Controller/Traits/UserValidationTrait.php:47 -msgid "User already active" -msgstr "Utilisateur dĆ©jĆ  actif" - -#: Controller/Traits/UserValidationTrait.php:53 -msgid "Reset password token was validated successfully" -msgstr "Le jeton de rĆ©initialisation du mot de passe a Ć©tĆ© validĆ© avec succĆØs" - -#: Controller/Traits/UserValidationTrait.php:58 -msgid "Reset password token could not be validated" -msgstr "Le jeton de rĆ©initialisation du mot de passe n'a pas pu ĆŖtre validĆ©" - -#: Controller/Traits/UserValidationTrait.php:62 -msgid "Invalid validation type" -msgstr "Type de validation invalide" - -#: Controller/Traits/UserValidationTrait.php:65 -msgid "Invalid token or user account already validated" -msgstr "Jeton invalide ou compte utilisateur dĆ©jĆ  activĆ©" - -#: Controller/Traits/UserValidationTrait.php:67 -msgid "Token already expired" -msgstr "Le jeton a dĆ©jĆ  expirĆ©" - -#: Controller/Traits/UserValidationTrait.php:93 -msgid "Token has been reset successfully. Please check your email." -msgstr "" -"Le jeton a Ć©tĆ© rĆ©initialisĆ© avec succĆØs. Veuillez consulter vos courriels." - -#: Controller/Traits/UserValidationTrait.php:102 -msgid "User {0} is already active" -msgstr "L'utilisateur {0} est dĆ©jĆ  actif" - -#: Email/EmailSender.php:39 -msgid "Your account validation link" -msgstr "Votre lien de validation de compte" - -#: Mailer/UsersMailer.php:55 -msgid "{0}Your reset password link" -msgstr "{0}Votre lien de rĆ©initialisation de mot de passe" - -#: Mailer/UsersMailer.php:78 -msgid "{0}Your social account validation link" -msgstr "{0}Votre lien de validation de compte social" - -#: Model/Behavior/PasswordBehavior.php:56 -msgid "Reference cannot be null" -msgstr "La rĆ©fĆ©rence ne peut pas ĆŖtre nulle" - -#: Model/Behavior/PasswordBehavior.php:61 -msgid "Token expiration cannot be empty" -msgstr "L'expiration du jeton ne peut pas ĆŖtre vide" - -#: Model/Behavior/PasswordBehavior.php:67;116 -msgid "User not found" -msgstr "Utilisateur non trouvĆ©" - -#: Model/Behavior/PasswordBehavior.php:71 -#: Model/Behavior/RegisterBehavior.php:111 -msgid "User account already validated" -msgstr "Compte utilisateur dĆ©jĆ  validĆ©" - -#: Model/Behavior/PasswordBehavior.php:78 -msgid "User not active" -msgstr "Utilisateur non activĆ©" - -#: Model/Behavior/PasswordBehavior.php:121 -msgid "The current password does not match" -msgstr "Le mot de passe actuel ne correspond pas" - -#: Model/Behavior/PasswordBehavior.php:124 -msgid "You cannot use the current password as the new one" -msgstr "" -"Vous ne pouvez pas utiliser le mot de passe actuel comme nouveau mot de passe" - -#: Model/Behavior/RegisterBehavior.php:89 -msgid "User not found for the given token and email." -msgstr "Utilisateur non trouvĆ© pour le jeton et le courriel spĆ©cifiĆ©s" - -#: Model/Behavior/RegisterBehavior.php:92 -msgid "Token has already expired user with no token" -msgstr "Le jeton a dĆ©jĆ  expirĆ© utilisateur sans jeton" - -#: Model/Behavior/SocialAccountBehavior.php:102;129 -msgid "Account already validated" -msgstr "Compte dĆ©jĆ  validĆ©" - -#: Model/Behavior/SocialAccountBehavior.php:105;132 -msgid "Account not found for the given token and email." -msgstr "Compte non trouvĆ© pour le jeton et le courriel spĆ©cifiĆ©s" - -#: Model/Behavior/SocialBehavior.php:56 -msgid "Unable to login user with reference {0}" -msgstr "Impossible d'identifier l'utilisateur avec la rĆ©fĆ©rence {0}" - -#: Model/Behavior/SocialBehavior.php:98 -msgid "Email not present" -msgstr "Courriel non prĆ©sent" - -#: Model/Table/UsersTable.php:82 -msgid "Your password does not match your confirm password. Please try again" -msgstr "" -"Votre mot de passe ne correspond pas Ć  la confirmation de mot de passe. " -"Veuillez rĆ©essayer" - -#: Model/Table/UsersTable.php:175 -msgid "Username already exists" -msgstr "Le nom d'utilisateur existe dĆ©jĆ " - -#: Model/Table/UsersTable.php:181 -msgid "Email already exists" -msgstr "Le courriel existe dĆ©jĆ " - -#: Model/Table/UsersTable.php:214 -msgid "Missing 'username' in options data" -msgstr "'username' manquant dans les donnĆ©es d'options" - -#: Shell/UsersShell.php:54 -msgid "Utilities for CakeDC Users Plugin" -msgstr "Utilitaires pour le Plugin CakeDC Users" - -#: Shell/UsersShell.php:55 -msgid "Activate an specific user" -msgstr "Activer un utilisateur spĆ©cifique" - -#: Shell/UsersShell.php:56 -msgid "Add a new superadmin user for testing purposes" -msgstr "" -"Ajouter un nouvel utilisateur super-administrateur pour des besoins de tests" - -#: Shell/UsersShell.php:57 -msgid "Add a new user" -msgstr "Ajouter un nouvel utilisateur" - -#: Shell/UsersShell.php:58 -msgid "Change the role for an specific user" -msgstr "Changer le rĆ“le d'un utilisateur spĆ©cifique" - -#: Shell/UsersShell.php:59 -msgid "Deactivate an specific user" -msgstr "DĆ©sactiver un utilisateur spĆ©cifique" - -#: Shell/UsersShell.php:60 -msgid "Delete an specific user" -msgstr "Supprimer un utilisateur spĆ©cifique" - -#: Shell/UsersShell.php:61 -msgid "Reset the password via email" -msgstr "RĆ©initialiser le mot de passe par courriel" - -#: Shell/UsersShell.php:62 -msgid "Reset the password for all users" -msgstr "RĆ©initialiser le mot de passe de tous les utilisateurs" - -#: Shell/UsersShell.php:63 -msgid "Reset the password for an specific user" -msgstr "RĆ©initialiser le mot de passe pour un utilisateur spĆ©cifique" - -#: Shell/UsersShell.php:98 -msgid "User added:" -msgstr "Utilisateur ajoutĆ© :" - -#: Shell/UsersShell.php:99;127 -msgid "Id: {0}" -msgstr "Identifiant : {0}" - -#: Shell/UsersShell.php:100;128 -msgid "Username: {0}" -msgstr "Nom d'utilisateur : {0}" - -#: Shell/UsersShell.php:101;129 -msgid "Email: {0}" -msgstr "Courriel : {0}" - -#: Shell/UsersShell.php:102;130 -msgid "Password: {0}" -msgstr "Mot de passe : {0}" - -#: Shell/UsersShell.php:126 -msgid "Superuser added:" -msgstr "Super-utilisateur ajoutĆ© :" - -#: Shell/UsersShell.php:132 -msgid "Superuser could not be added:" -msgstr "Le super-utilisateur n'a pas pu ĆŖtre ajoutĆ© :" - -#: Shell/UsersShell.php:135 -msgid "Field: {0} Error: {1}" -msgstr "Champ : {0} Erreur : {1}" - -#: Shell/UsersShell.php:153;179 -msgid "Please enter a password." -msgstr "Veuillez saisir un mot de passe." - -#: Shell/UsersShell.php:157 -msgid "Password changed for all users" -msgstr "Mot de passe changĆ© pour tous les utilisateurs" - -#: Shell/UsersShell.php:158;186 -msgid "New password: {0}" -msgstr "Nouveau mot de passe : {0}" - -#: Shell/UsersShell.php:176;204;282;324 -msgid "Please enter a username." -msgstr "Veuillez saisir un nom d'utilisateur." - -#: Shell/UsersShell.php:185 -msgid "Password changed for user: {0}" -msgstr "Mot de passe changĆ© pour l'utilisateur : {0}" - -#: Shell/UsersShell.php:207 -msgid "Please enter a role." -msgstr "Veuillez saisir un rĆ“le." - -#: Shell/UsersShell.php:213 -msgid "Role changed for user: {0}" -msgstr "RĆ“le changĆ© pour l'utilisateur : {0}" - -#: Shell/UsersShell.php:214 -msgid "New role: {0}" -msgstr "Nouveau rĆ“le : {0}" - -#: Shell/UsersShell.php:229 -msgid "User was activated: {0}" -msgstr "L'utilisateur a Ć©tĆ© activĆ© : {0}" - -#: Shell/UsersShell.php:244 -msgid "User was de-activated: {0}" -msgstr "L'utilisateur a Ć©tĆ© dĆ©sactivĆ© : {0]" - -#: Shell/UsersShell.php:256 -msgid "Please enter a username or email." -msgstr "Veuillez saisir un nom d'utilisateur ou un courriel." - -#: Shell/UsersShell.php:264 -msgid "" -"Please ask the user to check the email to continue with password reset " -"process" -msgstr "" -"Veuillez demander Ć  l'utilisateur de vĆ©rifier ses courriels pour poursuivre " -"la procĆ©dure de rĆ©initialisation du mot de passe." - -#: Shell/UsersShell.php:302 -msgid "The user was not found." -msgstr "L'utilisateur n'a pas Ć©tĆ© trouvĆ©." - -#: Shell/UsersShell.php:332 -msgid "The user {0} was not deleted. Please try again" -msgstr "L'utilisateur {0} n'a pas Ć©tĆ© supprimĆ©. Veuillez rĆ©essayer" - -#: Shell/UsersShell.php:334 -msgid "The user {0} was deleted successfully" -msgstr "L'utilisateur {0} a Ć©tĆ© supprimĆ© avec succĆØs" - -#: Template/Email/html/reset_password.ctp:21 -#: Template/Email/html/social_account_validation.ctp:14 -#: Template/Email/html/validation.ctp:21 -#: Template/Email/text/reset_password.ctp:20 -#: Template/Email/text/social_account_validation.ctp:22 -#: Template/Email/text/validation.ctp:20 -msgid "Hi {0}" -msgstr "Bonjour {0}" - -#: Template/Email/html/reset_password.ctp:24 -msgid "Reset your password here" -msgstr "RĆ©initialisez votre mot de passe ici" - -#: Template/Email/html/reset_password.ctp:27 -#: Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 -msgid "" -"If the link is not correcly displayed, please copy the following address in " -"your web browser {0}" -msgstr "" -"Si le lien n'est pas correctement affichĆ©, veuillez copier l'adresse " -"suivante dans votre navigateur web {0}" - -#: Template/Email/html/reset_password.ctp:30 -#: Template/Email/html/social_account_validation.ctp:35 -#: Template/Email/html/validation.ctp:30 -#: Template/Email/text/reset_password.ctp:24 -#: Template/Email/text/social_account_validation.ctp:26 -#: Template/Email/text/validation.ctp:24 -msgid "Thank you" -msgstr "Merci" - -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" -msgstr "Activez votre identification sociale ici" - -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" -msgstr "Activez votre compte ici" - -#: Template/Email/text/reset_password.ctp:22 -#: Template/Email/text/validation.ctp:22 -msgid "Please copy the following address in your web browser {0}" -msgstr "Veuillez copier l'adresse suivante dans votre navigateur web {0}" - -#: Template/Email/text/social_account_validation.ctp:24 -msgid "" -"Please copy the following address in your web browser to activate your " -"social login {0}" -msgstr "" -"Veuillez copier l'adresse suivante dans votre navigateur web pour activer " -"votre identification sociale {0}" - -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 -msgid "Actions" -msgstr "Actions" - -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 -#: Template/Users/view.ctp:19 -msgid "List Users" -msgstr "Lister les utilisateurs" - -#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:21 -msgid "List Accounts" -msgstr "Lister les comptes" - -#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 -msgid "Add User" -msgstr "Ajouter un utilisateur" - -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 -#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 -#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 -msgid "Username" -msgstr "Nom d'utilisateur" - -#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 -#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 -msgid "Email" -msgstr "Courriel" - -#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 -msgid "First name" -msgstr "PrĆ©nom" - -#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 -msgid "Last name" -msgstr "Nom" - -#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:44;75 -msgid "Active" -msgstr "Actif" - -#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 -#: Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:19 -msgid "Submit" -msgstr "Envoyer" - -#: Template/Users/change_password.ctp:5 -msgid "Please enter the new password" -msgstr "Veuillez entrer le nouveau mot de passe" - -#: Template/Users/change_password.ctp:10 -msgid "Current password" -msgstr "Mot de passe actuel" - -#: Template/Users/change_password.ctp:16 -msgid "New password" -msgstr "Nouveau mot de passe" - -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 -msgid "Confirm password" -msgstr "Confirmer le mot de passe" - -#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:101 -msgid "Delete" -msgstr "Supprimer" - -#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:18;101 -msgid "Are you sure you want to delete # {0}?" -msgstr "Ɗtes vous sĆ»r(e) de vouloir supprimler # {0} ?" - -#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 -msgid "Edit User" -msgstr "Modifier l'utilisateur" - -#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 -msgid "Token" -msgstr "Jeton" - -#: Template/Users/edit.ctp:41 -msgid "Token expires" -msgstr "Expiration du jeton" - -#: Template/Users/edit.ctp:44 -msgid "API token" -msgstr "Jeton d'API" - -#: Template/Users/edit.ctp:47 -msgid "Activation date" -msgstr "Date d'activiation" - -#: Template/Users/edit.ctp:50 -msgid "TOS date" -msgstr "Date CGU" - -#: Template/Users/index.ctp:15 -msgid "New {0}" -msgstr "Nouveau {0}" - -#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 -msgid "View" -msgstr "Voir" - -#: Template/Users/index.ctp:38 -msgid "Change password" -msgstr "Changer le mot de passe" - -#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 -msgid "Edit" -msgstr "Modifier" - -#: Template/Users/index.ctp:49 -msgid "previous" -msgstr "prĆ©cĆ©dent" - -#: Template/Users/index.ctp:51 -msgid "next" -msgstr "suivant" - -#: Template/Users/login.ctp:19 -msgid "Please enter your username and password" -msgstr "Merci de saisir votre nom d'utilisateur et votre mot de passe" - -#: Template/Users/login.ctp:29 -msgid "Remember me" -msgstr "Se souvenir de moi" - -#: Template/Users/login.ctp:37 -msgid "Register" -msgstr "S'inscrire" - -#: Template/Users/login.ctp:43 -msgid "Reset Password" -msgstr "RĆ©initialiser le mot de passe" - -#: Template/Users/login.ctp:48 -msgid "Login" -msgstr "S'identifier" - -#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 -msgid "{0} {1}" -msgstr "{0} {1}" - -#: Template/Users/profile.ctp:24 -msgid "Change Password" -msgstr "Changer le mot de passe" - -#: Template/Users/profile.ctp:34 -msgid "Social Accounts" -msgstr "Comptes sociaux" - -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 -msgid "Avatar" -msgstr "Photo de profil" - -#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 -msgid "Provider" -msgstr "Fournisseur" - -#: Template/Users/profile.ctp:40 -msgid "Link" -msgstr "Lien" - -#: Template/Users/profile.ctp:47 -msgid "Link to {0}" -msgstr "Lier Ć  {0}" - -#: Template/Users/register.ctp:20 -msgid "Password" -msgstr "Mot de passe" - -#: Template/Users/register.ctp:28 -msgid "Accept TOS conditions?" -msgstr "Accepter les CGU ?" - -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" -msgstr "Merci de saisir votre email pour rĆ©initialiser votre mot de passe" - -#: Template/Users/resend_token_validation.ctp:15 -msgid "Resend Validation email" -msgstr "RĆ©envoyer le courriel de validation" - -#: Template/Users/resend_token_validation.ctp:17 -msgid "Email or username" -msgstr "Courriel ou nom d'utilisateur" - -#: Template/Users/view.ctp:18 -msgid "Delete User" -msgstr "Supprimer l'utilisateur" - -#: Template/Users/view.ctp:20 -msgid "New User" -msgstr "Nouvel utilisateur" - -#: Template/Users/view.ctp:28;67 -msgid "Id" -msgstr "Identifiant" - -#: Template/Users/view.ctp:34 -msgid "First Name" -msgstr "PrĆ©nom" - -#: Template/Users/view.ctp:36 -msgid "Last Name" -msgstr "Nom" - -#: Template/Users/view.ctp:40 -msgid "Api Token" -msgstr "Jeton d'API" - -#: Template/Users/view.ctp:48;74 -msgid "Token Expires" -msgstr "Expiration du jeton" - -#: Template/Users/view.ctp:50 -msgid "Activation Date" -msgstr "Date d'activiation" - -#: Template/Users/view.ctp:52 -msgid "Tos Date" -msgstr "Date CGU" - -#: Template/Users/view.ctp:54;77 -msgid "Created" -msgstr "CrĆ©Ć© le" - -#: Template/Users/view.ctp:56;78 -msgid "Modified" -msgstr "ModifiĆ© le" - -#: Template/Users/view.ctp:63 -msgid "Related Accounts" -msgstr "Comptes liĆ©s" - -#: Template/Users/view.ctp:68 -msgid "User Id" -msgstr "Identifiant utilisateur" - -#: Template/Users/view.ctp:71 -msgid "Reference" -msgstr "RĆ©fĆ©rence" - -#: Template/Users/view.ctp:76 -msgid "Data" -msgstr "DonnĆ©es" - -#: View/Helper/UserHelper.php:46 -msgid "Sign in with" -msgstr "S'identifier avec" - -#: View/Helper/UserHelper.php:49 -msgid "fa fa-{0}" -msgstr "fa fa-{0}" - -#: View/Helper/UserHelper.php:52 -msgid "btn btn-social btn-{0} " -msgstr "btn btn-social btn-{0} " - -#: View/Helper/UserHelper.php:91 -msgid "Logout" -msgstr "Se dĆ©connecter" - -#: View/Helper/UserHelper.php:108 -msgid "Welcome, {0}" -msgstr "Bienvenue, {0}" - -#: View/Helper/UserHelper.php:131 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" -msgstr "" -"reCaptcha n'est pas configurĆ© ! Veuillez configurer Users.reCaptcha.key" - -#: Model/Behavior/RegisterBehavior.php:148 -msgid "This field is required" -msgstr "Ce champ est requis" - -#~ msgid "The old password does not match" -#~ msgstr "L'ancien mot de passe ne correspond pas" - -#~ msgid "" -#~ "If the link is not correctly displayed, please copy the following address " -#~ "in your web browser {0}" -#~ msgstr "" -#~ "Si le lien n'est pas correctement affichĆ©, veuillez copier l'adresse " -#~ "suivante dans votre navigateur web {0}" diff --git a/src/Locale/hu_HU/Users.mo b/src/Locale/hu_HU/Users.mo deleted file mode 100644 index ce8e248ce1e47f5ee7993b5aeebfaad260a498ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14725 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 diff --git a/src/Locale/hu_HU/Users.po b/src/Locale/hu_HU/Users.po deleted file mode 100644 index 4fb02e3f6..000000000 --- a/src/Locale/hu_HU/Users.po +++ /dev/null @@ -1,816 +0,0 @@ -# LANGUAGE translation of CakePHP Application -# Copyright YEAR NAME -# -msgid "" -msgstr "" -"Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2017-10-23 16:36+0200\n" -"PO-Revision-Date: 2017-10-23 17:17+0200\n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 2.0.1\n" -"Last-Translator: rrd \n" -"Language: hu_HU\n" - -#: Auth/SocialAuthenticate.php:456 -msgid "Provider cannot be empty" -msgstr "A kiszolgĆ”lĆ³ nem lehet Ć¼res" - -#: Controller/SocialAccountsController.php:52 -msgid "Account validated successfully" -msgstr "A fiĆ³k sikeresen ellenőrizve" - -#: Controller/SocialAccountsController.php:54 -msgid "Account could not be validated" -msgstr "A fiĆ³kot nem tudtam ellenőrizni" - -#: Controller/SocialAccountsController.php:57 -msgid "Invalid token and/or social account" -msgstr "ƉrvĆ©nytelen token Ć©s/vagy kƶzƶssĆ©gi fiĆ³k" - -#: Controller/SocialAccountsController.php:59;87 -msgid "Social Account already active" -msgstr "A kƶzƶssĆ©gi fiĆ³k mĆ”r aktĆ­v" - -#: Controller/SocialAccountsController.php:61 -msgid "Social Account could not be validated" -msgstr "A kƶzƶssĆ©gi fiĆ³k nem ellenőrizhető" - -#: Controller/SocialAccountsController.php:80 -msgid "Email sent successfully" -msgstr "Az email sikeresen elkĆ¼ldve" - -#: Controller/SocialAccountsController.php:82 -msgid "Email could not be sent" -msgstr "Az emailt nem tudtuk elkĆ¼ldeni" - -#: Controller/SocialAccountsController.php:85 -msgid "Invalid account" -msgstr "ƉrvĆ©nytelen fiĆ³k" - -#: Controller/SocialAccountsController.php:89 -msgid "Email could not be resent" -msgstr "Az emailt nem lehet ĆŗjrakĆ¼ldeni" - -#: Controller/Component/RememberMeComponent.php:68 -msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" -msgstr "" -"ƉrvĆ©nytelen alkalamzĆ”s sĆ³. Az alkalmazĆ”s sĆ³nak legalĆ”bb 256 bit (32 byte) " -"hosszĆŗnak kell lennie" - -#: Controller/Component/UsersAuthComponent.php:204 -msgid "You can't enable email validation workflow if use_email is false" -msgstr "Nem tudod engedĆ©lyezni az email ellenőrzĆ©st ha a use_email false" - -#: Controller/Traits/LinkSocialTrait.php:54 -msgid "Could not associate account, please try again." -msgstr "Nem sikerĆ¼lt tĆ”rsĆ­tani a fiĆ³kot, prĆ³bĆ”ld meg mĆ©g egyszer." - -#: Controller/Traits/LinkSocialTrait.php:77 -msgid "Social account was associated." -msgstr "A kƶzƶssĆ©gi fiĆ³k tĆ”rsĆ­tva." - -#: Controller/Traits/LoginTrait.php:104 -msgid "Issues trying to log in with your social account" -msgstr "Gond van a kƶzƶssĆ©gi fiĆ³kkal valĆ³ belĆ©pĆ©ssel." - -#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 -msgid "Please enter your email" -msgstr "Add meg az emailedet." - -#: Controller/Traits/LoginTrait.php:120 -msgid "" -"Your user has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"A felhasznĆ”lĆ³d mĆ©g nincs ellenőrizve. NĆ”zd meg az emailjeidet a teendőkĆ©rt." - -#: Controller/Traits/LoginTrait.php:125 -msgid "" -"Your social account has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"A kƶzƶssĆ©gi fiĆ³kod mĆ©g nincs ellenőrizve. NĆ”zd meg az emailjeidet a " -"teendőkĆ©rt." - -#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 -msgid "Invalid reCaptcha" -msgstr "ƉrvĆ©nytelen reCaptcha" - -#: Controller/Traits/LoginTrait.php:191 -msgid "You are already logged in" -msgstr "MĆ”r be vagy jelentkezve" - -#: Controller/Traits/LoginTrait.php:212 -msgid "Please enable Google Authenticator first." -msgstr "Előszƶr engedĆ©lyezd a Google Authenticatort." - -#: Controller/Traits/LoginTrait.php:287 -msgid "Verification code is invalid. Try again" -msgstr "Az ellenőrző kĆ³d Ć©rvĆ©nytelen. PrĆ³bĆ”ld meg Ćŗjra" - -#: Controller/Traits/LoginTrait.php:340 -msgid "Username or password is incorrect" -msgstr "A felhasznĆ”lĆ³i nĆ©v vagy a jelszĆ³ helytelen" - -#: Controller/Traits/LoginTrait.php:363 -msgid "You've successfully logged out" -msgstr "Sikeresen kijelentkeztĆ©l" - -#: Controller/Traits/PasswordManagementTrait.php:49;82 -#: Controller/Traits/ProfileTrait.php:50 -msgid "User was not found" -msgstr "A felhasznĆ”lĆ³ nem talĆ”lhatĆ³" - -#: Controller/Traits/PasswordManagementTrait.php:70;78;86 -msgid "Password could not be changed" -msgstr "A jelszĆ³t nem tudtuk mĆ³dosĆ­tani" - -#: Controller/Traits/PasswordManagementTrait.php:74 -msgid "Password has been changed successfully" -msgstr "A jelszĆ³ siekresen mĆ³dosĆ­tva" - -#: Controller/Traits/PasswordManagementTrait.php:84 -msgid "{0}" -msgstr "" - -#: Controller/Traits/PasswordManagementTrait.php:127 -msgid "Please check your email to continue with password reset process" -msgstr "NĆ©zd meg az emailjeidet a jelszĆ³ visszaĆ”llĆ­tĆ”s folytatĆ”sĆ”hoz" - -#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 -msgid "The password token could not be generated. Please try again" -msgstr "A jelszĆ³ token lĆ©trehozĆ”sa sikertelen. PrĆ³bĆ”ld meg Ćŗjra" - -#: Controller/Traits/PasswordManagementTrait.php:136 -#: Controller/Traits/UserValidationTrait.php:107 -msgid "User {0} was not found" -msgstr "A {0} felhasznĆ”lĆ³ nem talĆ”lhatĆ³" - -#: Controller/Traits/PasswordManagementTrait.php:138 -msgid "The user is not active" -msgstr "A felhasznĆ”lĆ³ nem aktĆ­v" - -#: Controller/Traits/PasswordManagementTrait.php:140 -#: Controller/Traits/UserValidationTrait.php:102;111 -msgid "Token could not be reset" -msgstr "A token nem Ć”llĆ­thatĆ³ vissza" - -#: Controller/Traits/PasswordManagementTrait.php:164 -msgid "Google Authenticator token was successfully reset" -msgstr "A Google Authenticator token sikeresen visszaĆ”llĆ­tva" - -#: Controller/Traits/ProfileTrait.php:54 -msgid "Not authorized, please login first" -msgstr "MĆ©g nem jelentkeztĆ©l be. Jelentkezz be" - -#: Controller/Traits/RegisterTrait.php:43 -msgid "You must log out to register a new user account" -msgstr "Ki kell lĆ©pned ahhoz, hogy Ćŗj fiĆ³kot tudj lĆ©trehozni" - -#: Controller/Traits/RegisterTrait.php:89 -msgid "The user could not be saved" -msgstr "A felhasznĆ”lĆ³t nem lehet menteni" - -#: Controller/Traits/RegisterTrait.php:123 -msgid "You have registered successfully, please log in" -msgstr "Sikeresen regisztrĆ”ltĆ”l, lĆ©pj be" - -#: Controller/Traits/RegisterTrait.php:125 -msgid "Please validate your account before log in" -msgstr "KĆ©rlek jitelesĆ­tsd a fiĆ³kodat mielőtt belĆ©pnĆ©l" - -#: Controller/Traits/SimpleCrudTrait.php:77;107 -msgid "The {0} has been saved" -msgstr "A {0} mentve" - -#: Controller/Traits/SimpleCrudTrait.php:81;111 -msgid "The {0} could not be saved" -msgstr "A {0} nincs mentve" - -#: Controller/Traits/SimpleCrudTrait.php:131 -msgid "The {0} has been deleted" -msgstr "A {0} tƶrƶlve" - -#: Controller/Traits/SimpleCrudTrait.php:133 -msgid "The {0} could not be deleted" -msgstr "A {0} nem lett tƶrƶlve" - -#: Controller/Traits/SocialTrait.php:40 -msgid "The reCaptcha could not be validated" -msgstr "A reCaptcha nem ellenőrizhető" - -#: Controller/Traits/UserValidationTrait.php:43 -msgid "User account validated successfully" -msgstr "A fiĆ³k sikeresen ellenőrizve" - -#: Controller/Traits/UserValidationTrait.php:45 -msgid "User account could not be validated" -msgstr "A fiĆ³kot nem sikerĆ¼lt ellnőrizni" - -#: Controller/Traits/UserValidationTrait.php:48 -msgid "User already active" -msgstr "A fiĆ³k mĆ”r aktĆ­v" - -#: Controller/Traits/UserValidationTrait.php:54 -msgid "Reset password token was validated successfully" -msgstr "A jelszĆ³ helyreĆ”llĆ­tĆ³ token sikeresen ellenőrizve" - -#: Controller/Traits/UserValidationTrait.php:62 -msgid "Reset password token could not be validated" -msgstr "A jelszĆ³ helyreĆ”llĆ­tĆ³ token ellenőrzĆ©se sikertelen" - -#: Controller/Traits/UserValidationTrait.php:66 -msgid "Invalid validation type" -msgstr "Helytelen ellenőrzĆ©s tĆ­pus" - -#: Controller/Traits/UserValidationTrait.php:69 -msgid "Invalid token or user account already validated" -msgstr "Helytelen token vagy a fiĆ³k mĆ”r ellenőrizve van" - -#: Controller/Traits/UserValidationTrait.php:71 -msgid "Token already expired" -msgstr "A token mĆ”r lejĆ”rt" - -#: Controller/Traits/UserValidationTrait.php:97 -msgid "Token has been reset successfully. Please check your email." -msgstr "A token helyreĆ”llĆ­tva. NĆ©zd meg az emailjeidet." - -#: Controller/Traits/UserValidationTrait.php:109 -msgid "User {0} is already active" -msgstr "{0} felhasznĆ”lĆ³ mĆ”r aktĆ­v" - -#: Mailer/UsersMailer.php:34 -msgid "Your account validation link" -msgstr "A fiĆ³kod hitelesĆ­tĆ©si linkje" - -#: Mailer/UsersMailer.php:52 -msgid "{0}Your reset password link" -msgstr "{0} A jelszĆ³ helyreĆ”llĆ­tĆ”s linkje" - -#: Mailer/UsersMailer.php:75 -msgid "{0}Your social account validation link" -msgstr "{0} A kƶzƶssĆ©gi fiĆ³kod ellenőrzĆ©si linkje" - -#: Model/Behavior/AuthFinderBehavior.php:49 -msgid "Missing 'username' in options data" -msgstr "HiĆ”nyzĆ³ 'username' az opciĆ³kban" - -#: Model/Behavior/LinkSocialBehavior.php:53 -msgid "Social account already associated to another user" -msgstr "A kƶzƶssĆ©gi fiĆ³k mĆ”r csatlakoztatva van egy mĆ”sik felhasznĆ”lĆ³hoz" - -#: Model/Behavior/PasswordBehavior.php:45 -msgid "Reference cannot be null" -msgstr "A hivatkozĆ”s nem lehet null" - -#: Model/Behavior/PasswordBehavior.php:50 -msgid "Token expiration cannot be empty" -msgstr "A token lejĆ”rat nme lehet Ć¼res" - -#: Model/Behavior/PasswordBehavior.php:56;117 -msgid "User not found" -msgstr "A felhasznĆ”lĆ³ nem talĆ”lhatĆ³" - -#: Model/Behavior/PasswordBehavior.php:60 -#: Model/Behavior/RegisterBehavior.php:112;205 -msgid "User account already validated" -msgstr "A felhasznĆ”lĆ³i fiĆ³k mĆ”r ellenőrizve van" - -#: Model/Behavior/PasswordBehavior.php:67 -msgid "User not active" -msgstr "A felhasznĆ”lĆ³ nem aktĆ­v" - -#: Model/Behavior/PasswordBehavior.php:122 -msgid "The current password does not match" -msgstr "A jelenlegi jelszĆ³ nem stimmel" - -#: Model/Behavior/PasswordBehavior.php:125 -msgid "You cannot use the current password as the new one" -msgstr "Nem lehet az Ćŗj jelszĆ³ azonos a rĆ©givel" - -#: Model/Behavior/RegisterBehavior.php:90 -msgid "User not found for the given token and email." -msgstr "Nem talĆ”lhatĆ³ felhasznĆ”lĆ³ ehhez a tokenhez Ć©s emailhez." - -#: Model/Behavior/RegisterBehavior.php:93 -msgid "Token has already expired user with no token" -msgstr "A token lejĆ”rt felhasznĆ”lĆ³ token nĆ©lkĆ¼l" - -#: Model/Behavior/SocialAccountBehavior.php:103;130 -msgid "Account already validated" -msgstr "A fiĆ³k mĆ”r ellenőrizve van" - -#: Model/Behavior/SocialAccountBehavior.php:106;133 -msgid "Account not found for the given token and email." -msgstr "Nem talĆ”lhatĆ³ fiĆ³k ehhez a tokenhez Ć©s emailhez." - -#: Model/Behavior/SocialBehavior.php:82 -msgid "Unable to login user with reference {0}" -msgstr "Nem tudom belĆ©pni a usert a {0} hivatkozĆ”ssal" - -#: Model/Behavior/SocialBehavior.php:121 -msgid "Email not present" -msgstr "HiĆ”nyzĆ³ email" - -#: Model/Table/UsersTable.php:81 -msgid "Your password does not match your confirm password. Please try again" -msgstr "A jelszavad Ć©s a jelszĆ³ megerősĆ­tĆ©s nem azonos. PrĆ³bĆ”ld meg Ćŗjra" - -#: Model/Table/UsersTable.php:173 -msgid "Username already exists" -msgstr "A felhasznĆ”lĆ³nĆ©v mĆ”r foglalt" - -#: Model/Table/UsersTable.php:179 -msgid "Email already exists" -msgstr "Az email mĆ”r foglalt" - -#: Shell/UsersShell.php:58 -msgid "Utilities for CakeDC Users Plugin" -msgstr "Eszkƶzƶk a CakeDC Users Puginhez" - -#: Shell/UsersShell.php:60 -msgid "Activate an specific user" -msgstr "Egy bizonyos felhasznĆ”lĆ³ aktivĆ”lĆ”sa" - -#: Shell/UsersShell.php:63 -msgid "Add a new superadmin user for testing purposes" -msgstr "ƚj superadmin hozzĆ”adĆ”sa tesztelĆ©si cĆ©llal" - -#: Shell/UsersShell.php:66 -msgid "Add a new user" -msgstr "ƚj felhasznĆ”lĆ³" - -#: Shell/UsersShell.php:69 -msgid "Change the role for an specific user" -msgstr "Egy felhasznĆ”lĆ³i szerep mĆ³dosĆ­tĆ”sa" - -#: Shell/UsersShell.php:72 -msgid "Deactivate an specific user" -msgstr "Egy felhasznĆ”lĆ³ deaktivĆ”lĆ”sa" - -#: Shell/UsersShell.php:75 -msgid "Delete an specific user" -msgstr "Egy felhasznĆ”lĆ³ tƶrlĆ©se" - -#: Shell/UsersShell.php:78 -msgid "Reset the password via email" -msgstr "JelszĆ³ helyreĆ”llĆ­tĆ”s emailben" - -#: Shell/UsersShell.php:81 -msgid "Reset the password for all users" -msgstr "Minden feĆ©hasznĆ”lĆ³ jelszavĆ”nak visszaĆ”llĆ­tĆ”sa" - -#: Shell/UsersShell.php:84 -msgid "Reset the password for an specific user" -msgstr "Egy felhasznĆ”lĆ³ jelszavĆ”nak visszaĆ”llĆ­tĆ”sa" - -#: Shell/UsersShell.php:133;159 -msgid "Please enter a password." -msgstr "Adj meg egy jelszĆ³t" - -#: Shell/UsersShell.php:137 -msgid "Password changed for all users" -msgstr "Mindne felhasznĆ”lĆ³ jelszava mĆ³dosĆ­tva" - -#: Shell/UsersShell.php:138;166 -msgid "New password: {0}" -msgstr "ƚj jelszĆ³: {0}" - -#: Shell/UsersShell.php:156;184;262;359 -msgid "Please enter a username." -msgstr "Adj meg egy felhasznĆ”lĆ³nevet." - -#: Shell/UsersShell.php:165 -msgid "Password changed for user: {0}" -msgstr "A {0} felhasznĆ”lĆ³ jelszava megvĆ”ltoztatva" - -#: Shell/UsersShell.php:187 -msgid "Please enter a role." -msgstr "Adj meg egy szerepet." - -#: Shell/UsersShell.php:193 -msgid "Role changed for user: {0}" -msgstr "{0} felhasznĆ”lĆ³ szerepe mĆ³dosĆ­tva" - -#: Shell/UsersShell.php:194 -msgid "New role: {0}" -msgstr "ƚj szerep: {0}" - -#: Shell/UsersShell.php:209 -msgid "User was activated: {0}" -msgstr "{0} felhasznĆ”lĆ³ aktivĆ”lva" - -#: Shell/UsersShell.php:224 -msgid "User was de-activated: {0}" -msgstr "{0} felhasznĆ”lĆ³ deaktivĆ”lva" - -#: Shell/UsersShell.php:236 -msgid "Please enter a username or email." -msgstr "Adj meg egy felhasznĆ”lĆ³nevet vagy egy emailt." - -#: Shell/UsersShell.php:244 -msgid "" -"Please ask the user to check the email to continue with password reset " -"process" -msgstr "" -"KĆ©rd meg a felhasznĆ”lĆ³t, hogy nĆ©zze meg az emailjeit, hogy folytatni tudja a " -"jelszĆ³ visszaĆ”llĆ­tĆ”si folyamatot" - -#: Shell/UsersShell.php:308 -msgid "Superuser added:" -msgstr "Superuser hozzĆ”adva:" - -#: Shell/UsersShell.php:310 -msgid "User added:" -msgstr "A felhasznĆ”lĆ³ hozzĆ”adva:" - -#: Shell/UsersShell.php:312 -msgid "Id: {0}" -msgstr "" - -#: Shell/UsersShell.php:313 -msgid "Username: {0}" -msgstr "FelhasznĆ”lĆ³nĆ©v: {0}" - -#: Shell/UsersShell.php:314 -msgid "Email: {0}" -msgstr "" - -#: Shell/UsersShell.php:315 -msgid "Role: {0}" -msgstr "Szerep: {0}" - -#: Shell/UsersShell.php:316 -msgid "Password: {0}" -msgstr "JelszĆ³: {0}" - -#: Shell/UsersShell.php:318 -msgid "User could not be added:" -msgstr "A felhasznĆ”lĆ³t ne tudtuk hozzĆ”adni:" - -#: Shell/UsersShell.php:321 -msgid "Field: {0} Error: {1}" -msgstr "Mező: {0} Hiba: {1}" - -#: Shell/UsersShell.php:337 -msgid "The user was not found." -msgstr "A felhasznĆ”lĆ³ nem talĆ”lhatĆ³" - -#: Shell/UsersShell.php:367 -msgid "The user {0} was not deleted. Please try again" -msgstr "{0} felhasznĆ”lĆ³ nem lett tƶrƶlve. PrĆ³bĆ”ld meg Ćŗjra" - -#: Shell/UsersShell.php:369 -msgid "The user {0} was deleted successfully" -msgstr "{0} felhasznĆ”lĆ³ sikeresen tƶrƶlve" - -#: Template/Email/html/reset_password.ctp:21 -#: Template/Email/html/social_account_validation.ctp:14 -#: Template/Email/html/validation.ctp:21 -#: Template/Email/text/reset_password.ctp:20 -#: Template/Email/text/social_account_validation.ctp:22 -#: Template/Email/text/validation.ctp:20 -msgid "Hi {0}" -msgstr "Szia {0}" - -#: Template/Email/html/reset_password.ctp:24 -msgid "Reset your password here" -msgstr "JelszĆ³ visszaĆ”llĆ­tĆ”s" - -#: Template/Email/html/reset_password.ctp:27 -#: Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 -msgid "" -"If the link is not correctly displayed, please copy the following address in " -"your web browser {0}" -msgstr "" -"Ha a link nem jelenik meg jĆ³l, akkor mĆ”sold be ezt a cĆ­met a bƶngĆ©sződbe {0}" - -#: Template/Email/html/reset_password.ctp:34 -#: Template/Email/html/social_account_validation.ctp:39 -#: Template/Email/html/validation.ctp:34 -#: Template/Email/text/reset_password.ctp:28 -#: Template/Email/text/social_account_validation.ctp:30 -#: Template/Email/text/validation.ctp:28 -msgid "Thank you" -msgstr "Kƶszi" - -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" -msgstr "AktivĆ”ld a kƶzƶssĆ©gi fiĆ³kodat" - -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" -msgstr "AktivĆ”ld a fiĆ³kodat" - -#: Template/Email/text/reset_password.ctp:22 -#: Template/Email/text/validation.ctp:22 -msgid "Please copy the following address in your web browser {0}" -msgstr "MĆ”sold be a bƶngĆ©sződbe ezt a cĆ­met {0}" - -#: Template/Email/text/social_account_validation.ctp:24 -msgid "" -"Please copy the following address in your web browser to activate your " -"social login {0}" -msgstr "" -"MĆ”sold be a bƶngĆ©sződbe ezt a cĆ­met a kƶzƶssĆ©gi fiĆ³kod aktivĆ”lĆ”sĆ”hoz {0}" - -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 -msgid "Actions" -msgstr "Műveletek" - -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:23 -msgid "List Users" -msgstr "FelhasznĆ”lĆ³k" - -#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 -msgid "Add User" -msgstr "ƚj felhasznĆ”lĆ³" - -#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 -#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 -#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 -msgid "Username" -msgstr "FelhasznĆ”lĆ³i nĆ©v" - -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 -#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 -msgid "Email" -msgstr "" - -#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 -msgid "Password" -msgstr "JelszĆ³" - -#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 -msgid "First name" -msgstr "KeresztnĆ©v" - -#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 -msgid "Last name" -msgstr "CsalĆ”di nĆ©v" - -#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:49;74 -msgid "Active" -msgstr "AktĆ­v" - -#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 -#: Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:19 -msgid "Submit" -msgstr "Ment" - -#: Template/Users/change_password.ctp:5 -msgid "Please enter the new password" -msgstr "Add meg az Ćŗj jelszĆ³t" - -#: Template/Users/change_password.ctp:10 -msgid "Current password" -msgstr "Jelenlegi jelszĆ³" - -#: Template/Users/change_password.ctp:16 -msgid "New password" -msgstr "ƚj jelszĆ³" - -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 -msgid "Confirm password" -msgstr "JelszĆ³ megerősĆ­tĆ©se" - -#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 -msgid "Delete" -msgstr "TƶrlĆ©s" - -#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:21 -msgid "Are you sure you want to delete # {0}?" -msgstr "Biztos tƶrlƶd # {0}?" - -#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 -msgid "Edit User" -msgstr "FelhasznĆ”lĆ³ mĆ³dosĆ­tĆ”sa" - -#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 -msgid "Token" -msgstr "" - -#: Template/Users/edit.ctp:41 -msgid "Token expires" -msgstr "Token lejĆ”rat" - -#: Template/Users/edit.ctp:44 -msgid "API token" -msgstr "" - -#: Template/Users/edit.ctp:47 -msgid "Activation date" -msgstr "AktivĆ”lĆ”s dĆ”tuma" - -#: Template/Users/edit.ctp:50 -msgid "TOS date" -msgstr "FelhasznĆ”lĆ³ feltĆ©telek dĆ”tuma" - -#: Template/Users/edit.ctp:63 -msgid "Reset Google Authenticator Token" -msgstr "Google Authenticator Token visszaĆ”llĆ­tĆ”sa" - -#: Template/Users/edit.ctp:69 -msgid "Are you sure you want to reset token for user \"{0}\"?" -msgstr "" -"Biztos vagy benne, hogy vissza akarod Ć”llĆ­tani {0} felhasznĆ”lĆ³ tokenjĆ©t?" - -#: Template/Users/index.ctp:15 -msgid "New {0}" -msgstr "ƚj {0}" - -#: Template/Users/index.ctp:37 -msgid "View" -msgstr "Mutat" - -#: Template/Users/index.ctp:38 -msgid "Change password" -msgstr "JElszĆ³ mĆ³dosĆ­tĆ”s" - -#: Template/Users/index.ctp:39 -msgid "Edit" -msgstr "Szerkeszt" - -#: Template/Users/index.ctp:49 -msgid "previous" -msgstr "előző" - -#: Template/Users/index.ctp:51 -msgid "next" -msgstr "kƶvetkező" - -#: Template/Users/login.ctp:19 -msgid "Please enter your username and password" -msgstr "Add meg a felhasznĆ”lĆ³i nevedet Ć©s a jelszavadat" - -#: Template/Users/login.ctp:29 -msgid "Remember me" -msgstr "EmlĆ©kezz rĆ”m" - -#: Template/Users/login.ctp:37 -msgid "Register" -msgstr "RegisztrĆ”lok" - -#: Template/Users/login.ctp:43 -msgid "Reset Password" -msgstr "JelszĆ³ visszaĆ”llĆ­tĆ”s" - -#: Template/Users/login.ctp:48 -msgid "Login" -msgstr "BelĆ©pĆ©s" - -#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 -msgid "{0} {1}" -msgstr "" - -#: Template/Users/profile.ctp:27 -msgid "Change Password" -msgstr "JelszĆ³ mĆ³dosĆ­tĆ”s" - -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 -msgid "Social Accounts" -msgstr "KƶzƶssĆ©gi fiĆ³kok" - -#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 -msgid "Avatar" -msgstr "" - -#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 -msgid "Provider" -msgstr "KiszolgĆ”lĆ³" - -#: Template/Users/profile.ctp:44 -msgid "Link" -msgstr "" - -#: Template/Users/profile.ctp:51 -msgid "Link to {0}" -msgstr "KapcsolĆ³dva: {0}" - -#: Template/Users/register.ctp:29 -msgid "Accept TOS conditions?" -msgstr "Elfogadod a felhasznĆ”lĆ³ feltĆ©teleket?" - -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" -msgstr "Add meg az emailcĆ­medet a jelszĆ³ helyreĆ”llĆ­tĆ”shoz" - -#: Template/Users/resend_token_validation.ctp:15 -msgid "Resend Validation email" -msgstr "Ellenƶrző email ĆŗjrakĆ¼ldĆ©se" - -#: Template/Users/resend_token_validation.ctp:17 -msgid "Email or username" -msgstr "Email vagy felhasznĆ”lĆ³ nĆ©v" - -#: Template/Users/verify.ctp:13 -msgid "Verification Code" -msgstr "Ellenƶrző kĆ³d" - -#: Template/Users/verify.ctp:15 -msgid "" -" " -"Verify" -msgstr "" -" " -"Ellenőriz" - -#: Template/Users/view.ctp:19 -msgid "Delete User" -msgstr "FelhasznĆ”lĆ³ tƶrlĆ©se" - -#: Template/Users/view.ctp:24 -msgid "New User" -msgstr "ƚj felhasznĆ”lĆ³" - -#: Template/Users/view.ctp:31 -msgid "Id" -msgstr "" - -#: Template/Users/view.ctp:37 -msgid "First Name" -msgstr "KeresztnĆ©v" - -#: Template/Users/view.ctp:39 -msgid "Last Name" -msgstr "CsalĆ”di nĆ©v" - -#: Template/Users/view.ctp:41 -msgid "Role" -msgstr "Szerep" - -#: Template/Users/view.ctp:45 -msgid "Api Token" -msgstr "" - -#: Template/Users/view.ctp:53 -msgid "Token Expires" -msgstr "Token lejĆ”rat" - -#: Template/Users/view.ctp:55 -msgid "Activation Date" -msgstr "AktivĆ”lĆ”s dĆ”tuma" - -#: Template/Users/view.ctp:57 -msgid "Tos Date" -msgstr "FelhasznĆ”lĆ³i feltĆ©telek dĆ”tuma" - -#: Template/Users/view.ctp:59;75 -msgid "Created" -msgstr "LĆ©trehozva" - -#: Template/Users/view.ctp:61;76 -msgid "Modified" -msgstr "MĆ³dosĆ­tva" - -#: View/Helper/UserHelper.php:45 -msgid "Sign in with" -msgstr "BelĆ©pĆ©s ezzel" - -#: View/Helper/UserHelper.php:48 -msgid "fa fa-{0}" -msgstr "" - -#: View/Helper/UserHelper.php:57 -msgid "btn btn-social btn-{0} " -msgstr "" - -#: View/Helper/UserHelper.php:106 -msgid "Logout" -msgstr "KilĆ©p" - -#: View/Helper/UserHelper.php:123 -msgid "Welcome, {0}" -msgstr "Ɯdv {0}!" - -#: View/Helper/UserHelper.php:146 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" -msgstr "" -"A reCaptcha nincs beĆ”llĆ­tva! Ellenőrizd a Users.reCaptcha.key beĆ”llĆ­tĆ”st" - -#: View/Helper/UserHelper.php:205 -msgid "btn btn-social btn-{0}" -msgstr "" - -#: View/Helper/UserHelper.php:211 -msgid "Connected with {0}" -msgstr "ƖsszekapcsolĆ³dva ezzel: {0}" - -#: View/Helper/UserHelper.php:216 -msgid "Connect with {0}" -msgstr "KapcsolĆ³dĆ”s ehhez: {0} " diff --git a/src/Locale/it_IT/Users.mo b/src/Locale/it_IT/Users.mo deleted file mode 100644 index f242989f460433ffb9e21dea5b545ccbdf20e4d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15385 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 diff --git a/src/Locale/it_IT/Users.po b/src/Locale/it_IT/Users.po deleted file mode 100644 index 80176186a..000000000 --- a/src/Locale/it_IT/Users.po +++ /dev/null @@ -1,783 +0,0 @@ -# LANGUAGE translation of CakePHP Application -# Copyright 2010 - 2016, Cake Development Corporation (http://cakedc.com) -# -msgid "" -msgstr "" -"Project-Id-Version: CakeDC Users\n" -"POT-Creation-Date: 2017-12-21 12:01+0100\n" -"PO-Revision-Date: 2018-01-12 17:06+0100\n" -"Last-Translator: Silvia Ghignone \n" -"Language-Team: CakeDC \n" -"Language: it_IT\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 2.0.5\n" - -#: Auth/ApiKeyAuthenticate.php:73 -msgid "Type {0} is not valid" -msgstr "Il tipo {0} non ĆØ valido" - -#: Auth/ApiKeyAuthenticate.php:77 -msgid "Type {0} has no associated callable" -msgstr "Il tipo {0} non ha nessuna funzione di chiamata associabile" - -#: Auth/ApiKeyAuthenticate.php:86 -msgid "SSL is required for ApiKey Authentication" -msgstr "SSL ĆØ richiesto per ApiKey Authentication" - -#: Auth/SimpleRbacAuthorize.php:142 -msgid "Missing configuration file: \"config/{0}.php\". Using default permissions" -msgstr "File di configurazione mancante: \"config/{0}.php\". Utilizzo dei permessi di default" - -#: Auth/SocialAuthenticate.php:432 -msgid "Provider cannot be empty" -msgstr "Il campo Provider non puĆ² essere vuoto" - -#: Auth/Rules/AbstractRule.php:78 -msgid "" -"Table alias is empty, please define a table alias, we could not extract a default table from the " -"request" -msgstr "" -"L'alias della tabella ĆØ vuoto, per favore definire un alias tabella, non potremmo estrarre una tabella " -"di default dalla richiesta" - -#: Auth/Rules/Owner.php:67;70 -msgid "Missing column {0} in table {1} while checking ownership permissions for user {2}" -msgstr "" -"Colonna {0} mancante nella tabella {1} durante la verifica dei \"\"permessi di proprietĆ  per l'utente " -"{2}" - -#: Controller/SocialAccountsController.php:52 -msgid "Account validated successfully" -msgstr "Account convalidato con successo" - -#: Controller/SocialAccountsController.php:54 -msgid "Account could not be validated" -msgstr "Non ĆØ stato possibile convalidare l'account" - -#: Controller/SocialAccountsController.php:57 -msgid "Invalid token and/or social account" -msgstr "Token e/o account social non valido" - -#: Controller/SocialAccountsController.php:59;87 -msgid "Social Account already active" -msgstr "Account Social giĆ  attivo" - -#: Controller/SocialAccountsController.php:61 -msgid "Social Account could not be validated" -msgstr "Non ĆØ stato possibile convalidare l'Account Social" - -#: Controller/SocialAccountsController.php:80 -msgid "Email sent successfully" -msgstr "Email inviata con successo" - -#: Controller/SocialAccountsController.php:82 -msgid "Email could not be sent" -msgstr "Impossibile inviare l'email" - -#: Controller/SocialAccountsController.php:85 -msgid "Invalid account" -msgstr "Account non valido" - -#: Controller/SocialAccountsController.php:89 -msgid "Email could not be resent" -msgstr "Non ĆØ stato possibile reinviare l'email" - -#: Controller/Component/RememberMeComponent.php:69 -msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" -msgstr "App salt non valido. App salt deve essere almeno lungo 256 bits (32 bytes)" - -#: Controller/Component/UsersAuthComponent.php:178 -msgid "You can't enable email validation workflow if use_email is false" -msgstr "Non ĆØ possibile abilitare il workflow di validazione email se use_email ĆØ false" - -#: Controller/Traits/LoginTrait.php:96 -msgid "Issues trying to log in with your social account" -msgstr "Si sono verificati dei problemi nel tentativo di effettuare il log in col tuo account social" - -#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 -msgid "Please enter your email" -msgstr "Per favore inseirsci la tua email" - -#: Controller/Traits/LoginTrait.php:108 -msgid "Your user has not been validated yet. Please check your inbox for instructions" -msgstr "" -"Il vostro utente non ĆØ ancora stato convalidato. Per favore verifica le tue email in arrivoper " -"ottenere le istruzioni" - -#: Controller/Traits/LoginTrait.php:110 -msgid "Your social account has not been validated yet. Please check your inbox for instructions" -msgstr "" -"Il tuo account social non ĆØ stato ancora convalidato. Per favore verifica la tuacasella di posta " -"elettronica per maggiori informazioni" - -#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 -msgid "Invalid reCaptcha" -msgstr "reCaptcha non valida" - -#: Controller/Traits/LoginTrait.php:171 -msgid "You are already logged in" -msgstr "E' giĆ Ā  stato effettuato il log in" - -#: Controller/Traits/LoginTrait.php:217 -msgid "Username or password is incorrect" -msgstr "Username o password non corretti" - -#: Controller/Traits/LoginTrait.php:238 -msgid "You've successfully logged out" -msgstr "Log out effettuato con successo" - -#: Controller/Traits/PasswordManagementTrait.php:47;76 Controller/Traits/ProfileTrait.php:49 -msgid "User was not found" -msgstr "Utente non trovato" - -#: Controller/Traits/PasswordManagementTrait.php:64;72;80 -msgid "Password could not be changed" -msgstr "Non ĆØ stato possibile cambiare la password" - -#: Controller/Traits/PasswordManagementTrait.php:68 -msgid "Password has been changed successfully" -msgstr "Password modificata con successo" - -#: Controller/Traits/PasswordManagementTrait.php:78 -msgid "{0}" -msgstr "{0}" - -#: Controller/Traits/PasswordManagementTrait.php:120 -msgid "Please check your email to continue with password reset process" -msgstr "Controllare la propria email per continuare col processo di ripristino della password" - -#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 -msgid "The password token could not be generated. Please try again" -msgstr "Non ĆØ stato possibile generare il token della password. Per favore riprovare" - -#: Controller/Traits/PasswordManagementTrait.php:129 Controller/Traits/UserValidationTrait.php:100 -msgid "User {0} was not found" -msgstr "Utente {0} non trovato" - -#: Controller/Traits/PasswordManagementTrait.php:131 -msgid "The user is not active" -msgstr "Utente non attivo" - -#: Controller/Traits/PasswordManagementTrait.php:133 Controller/Traits/UserValidationTrait.php:95;104 -msgid "Token could not be reset" -msgstr "Non ĆØ stato possibile ripristinare il token" - -#: Controller/Traits/ProfileTrait.php:53 -msgid "Not authorized, please login first" -msgstr "Non autorizzato, per favore effettuare prima il login" - -#: Controller/Traits/RegisterTrait.php:42 -msgid "You must log out to register a new user account" -msgstr "Per registrare un nuovo account utente, effettuare prima il log out" - -#: Controller/Traits/RegisterTrait.php:88 -msgid "The user could not be saved" -msgstr "Registrazione utente non riuscita" - -#: Controller/Traits/RegisterTrait.php:122 -msgid "You have registered successfully, please log in" -msgstr "Registrazione avvenuta con successo, per favore effettuare il log in" - -#: Controller/Traits/RegisterTrait.php:124 -msgid "Please validate your account before log in" -msgstr "Per favore convalida il tuo account prima di effettuare il log in" - -#: Controller/Traits/SimpleCrudTrait.php:76;106 -msgid "The {0} has been saved" -msgstr "{0} ĆØ stato salvato" - -#: Controller/Traits/SimpleCrudTrait.php:80;110 -msgid "The {0} could not be saved" -msgstr "Non ĆØ stato possibile salvare {0}" - -#: Controller/Traits/SimpleCrudTrait.php:130 -msgid "The {0} has been deleted" -msgstr "{0} ĆØ stato cancellato" - -#: Controller/Traits/SimpleCrudTrait.php:132 -msgid "The {0} could not be deleted" -msgstr "Non ĆØ stato possibile cancellare {0}" - -#: Controller/Traits/SocialTrait.php:39 -msgid "The reCaptcha could not be validated" -msgstr "Non ĆØ stato possibile convalidare la reCaptcha" - -#: Controller/Traits/UserValidationTrait.php:42 -msgid "User account validated successfully" -msgstr "Account utente convalidato con successo" - -#: Controller/Traits/UserValidationTrait.php:44 -msgid "User account could not be validated" -msgstr "Non ĆØ stato possibile convalidare l'account utente" - -#: Controller/Traits/UserValidationTrait.php:47 -msgid "User already active" -msgstr "Utente giĆ  attivo" - -#: Controller/Traits/UserValidationTrait.php:53 -msgid "Reset password token was validated successfully" -msgstr "Il token per il ripristino password ĆØ stato convalidato con successo" - -#: Controller/Traits/UserValidationTrait.php:58 -msgid "Reset password token could not be validated" -msgstr "Non ĆØ stato possibile convalidare il token per il ripristino della password" - -#: Controller/Traits/UserValidationTrait.php:62 -msgid "Invalid validation type" -msgstr "Tipo di validazione non valido" - -#: Controller/Traits/UserValidationTrait.php:65 -msgid "Invalid token or user account already validated" -msgstr "Toke non valido o account utente giĆ  convalidato" - -#: Controller/Traits/UserValidationTrait.php:67 -msgid "Token already expired" -msgstr "Token giĆ  scaduto" - -#: Controller/Traits/UserValidationTrait.php:93 -msgid "Token has been reset successfully. Please check your email." -msgstr "Il token ĆØ stato ripristinato con successo. Per favore verificare la propria email." - -#: Controller/Traits/UserValidationTrait.php:102 -msgid "User {0} is already active" -msgstr "L'Utente {0} ĆØ giĆ  attivo" - -#: Email/EmailSender.php:39 -msgid "Your account validation link" -msgstr "Il tuo link per convalidare l'account" - -#: Mailer/UsersMailer.php:55 -msgid "{0}Your reset password link" -msgstr "{0}Ecco il tuo link per ripristinare la password" - -#: Mailer/UsersMailer.php:78 -msgid "{0}Your social account validation link" -msgstr "{0}Ecco il tuo link per convalidare il tuo account social" - -#: Model/Behavior/PasswordBehavior.php:56 -msgid "Reference cannot be null" -msgstr "La referenza non puĆ² essere nulla" - -#: Model/Behavior/PasswordBehavior.php:61 -msgid "Token expiration cannot be empty" -msgstr "La scadenza del Token non puĆ² essere vuota" - -#: Model/Behavior/PasswordBehavior.php:67;116 -msgid "User not found" -msgstr "Utente non trovato" - -#: Model/Behavior/PasswordBehavior.php:71 Model/Behavior/RegisterBehavior.php:111 -msgid "User account already validated" -msgstr "Account utente giĆ  convalidato" - -#: Model/Behavior/PasswordBehavior.php:78 -msgid "User not active" -msgstr "Utente non attivo" - -#: Model/Behavior/PasswordBehavior.php:121 -msgid "The current password does not match" -msgstr "L'attuale password non corrisponde" - -#: Model/Behavior/PasswordBehavior.php:124 -msgid "You cannot use the current password as the new one" -msgstr "Non puoi utilizzare la password attuale come nuova password" - -#: Model/Behavior/RegisterBehavior.php:89 -msgid "User not found for the given token and email." -msgstr "Utente non trovato per l'email ed il token forniti." - -#: Model/Behavior/RegisterBehavior.php:92 -msgid "Token has already expired user with no token" -msgstr "Il token ĆØ giĆ  scaduto utente senza token" - -#: Model/Behavior/SocialAccountBehavior.php:102;129 -msgid "Account already validated" -msgstr "Account giĆ  convalidato" - -#: Model/Behavior/SocialAccountBehavior.php:105;132 -msgid "Account not found for the given token and email." -msgstr "Account non trovato per l'email ed il token forniti." - -#: Model/Behavior/SocialBehavior.php:56 -msgid "Unable to login user with reference {0}" -msgstr "Impossibile effettuare il login per l'utente con referenza {0}" - -#: Model/Behavior/SocialBehavior.php:98 -msgid "Email not present" -msgstr "Email non presente" - -#: Model/Table/UsersTable.php:82 -msgid "Your password does not match your confirm password. Please try again" -msgstr "La password non corrisponde con quella inserita nella conferma password.Per favore riprova" - -#: Model/Table/UsersTable.php:175 -msgid "Username already exists" -msgstr "Username giĆ  esistente" - -#: Model/Table/UsersTable.php:181 -msgid "Email already exists" -msgstr "Email giĆ  esistente" - -#: Model/Table/UsersTable.php:214 -msgid "Missing 'username' in options data" -msgstr "'username' mancante nelle opzioni dati" - -#: Shell/UsersShell.php:54 -msgid "Utilities for CakeDC Users Plugin" -msgstr "UtilitĆ  per Plugin CakeDC Users" - -#: Shell/UsersShell.php:55 -msgid "Activate an specific user" -msgstr "Attiva un utente specifico" - -#: Shell/UsersShell.php:56 -msgid "Add a new superadmin user for testing purposes" -msgstr "Aggiunge un nuovo superadmin per scopi di test" - -#: Shell/UsersShell.php:57 -msgid "Add a new user" -msgstr "Aggiungi un nuovo utente" - -#: Shell/UsersShell.php:58 -msgid "Change the role for an specific user" -msgstr "Cambia il ruolo per un utente specifico" - -#: Shell/UsersShell.php:59 -msgid "Deactivate an specific user" -msgstr "Disattiva un utente specifico" - -#: Shell/UsersShell.php:60 -msgid "Delete an specific user" -msgstr "Cancella un utente specifico" - -#: Shell/UsersShell.php:61 -msgid "Reset the password via email" -msgstr "Ripristina la password per email" - -#: Shell/UsersShell.php:62 -msgid "Reset the password for all users" -msgstr "Ripristina la password per tutti gli utenti" - -#: Shell/UsersShell.php:63 -msgid "Reset the password for an specific user" -msgstr "Ripristina la password per un utente specifico" - -#: Shell/UsersShell.php:98 -msgid "User added:" -msgstr "Utente aggiunto:" - -#: Shell/UsersShell.php:99;127 -msgid "Id: {0}" -msgstr "Identificatore : {0}" - -#: Shell/UsersShell.php:100;128 -msgid "Username: {0}" -msgstr "Nome utente: {0}" - -#: Shell/UsersShell.php:101;129 -msgid "Email: {0}" -msgstr "Email : {0}" - -#: Shell/UsersShell.php:102;130 -msgid "Password: {0}" -msgstr "Password: {0}" - -#: Shell/UsersShell.php:126 -msgid "Superuser added:" -msgstr "Superuser aggiunto :" - -#: Shell/UsersShell.php:132 -msgid "Superuser could not be added:" -msgstr "Lo Superuser non puĆ² essere aggiunto :" - -#: Shell/UsersShell.php:135 -msgid "Field: {0} Error: {1}" -msgstr "Campo : {0} Errore : {1}" - -#: Shell/UsersShell.php:153;179 -msgid "Please enter a password." -msgstr "Per favore inserire una password." - -#: Shell/UsersShell.php:157 -msgid "Password changed for all users" -msgstr "Password cambiata per tutti gli utenti" - -#: Shell/UsersShell.php:158;186 -msgid "New password: {0}" -msgstr "Nuova password : {0}" - -#: Shell/UsersShell.php:176;204;282;324 -msgid "Please enter a username." -msgstr "Per favore inserire un nome utente." - -#: Shell/UsersShell.php:185 -msgid "Password changed for user: {0}" -msgstr "Password cambiata per l'utente : {0}" - -#: Shell/UsersShell.php:207 -msgid "Please enter a role." -msgstr "Per favore inserire un ruolo." - -#: Shell/UsersShell.php:213 -msgid "Role changed for user: {0}" -msgstr "Ruolo modificato per l'utente: {0}" - -#: Shell/UsersShell.php:214 -msgid "New role: {0}" -msgstr "Nuovo ruolo: {0}" - -#: Shell/UsersShell.php:229 -msgid "User was activated: {0}" -msgstr "Utente attivato: {0}" - -#: Shell/UsersShell.php:244 -msgid "User was de-activated: {0}" -msgstr "Utente disattivato: {0]" - -#: Shell/UsersShell.php:256 -msgid "Please enter a username or email." -msgstr "Per favore inserire un nome utente o email." - -#: Shell/UsersShell.php:264 -msgid "Please ask the user to check the email to continue with password reset process" -msgstr "" -"Per favore richiedere all'utente di controllare l'email per continuare con la procedura di ripristino " -"password" - -#: Shell/UsersShell.php:302 -msgid "The user was not found." -msgstr "Utente non trovato." - -#: Shell/UsersShell.php:332 -msgid "The user {0} was not deleted. Please try again" -msgstr "L'Utente {0} non ĆØ stato cancellato. Per favore riprovare" - -#: Shell/UsersShell.php:334 -msgid "The user {0} was deleted successfully" -msgstr "L'utente {0} ĆØ stato cancellato con successo" - -#: Template/Email/html/reset_password.ctp:21 Template/Email/html/social_account_validation.ctp:14 -#: Template/Email/html/validation.ctp:21 Template/Email/text/reset_password.ctp:20 -#: Template/Email/text/social_account_validation.ctp:22 Template/Email/text/validation.ctp:20 -msgid "Hi {0}" -msgstr "Ciao {0}" - -#: Template/Email/html/reset_password.ctp:24 -msgid "Reset your password here" -msgstr "Ripristina la tua password qui" - -#: Template/Email/html/reset_password.ctp:27 Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 -msgid "If the link is not correcly displayed, please copy the following address in your web browser {0}" -msgstr "" -"Se il link non viene mostrato correttamente, per favore copia il seguente indirizzo nel tuo browser " -"web {0}" - -#: Template/Email/html/reset_password.ctp:30 Template/Email/html/social_account_validation.ctp:35 -#: Template/Email/html/validation.ctp:30 Template/Email/text/reset_password.ctp:24 -#: Template/Email/text/social_account_validation.ctp:26 Template/Email/text/validation.ctp:24 -msgid "Thank you" -msgstr "Grazie" - -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" -msgstr "Attiva qui il tuo login social" - -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" -msgstr "Attiva qui il tuo account" - -#: Template/Email/text/reset_password.ctp:22 Template/Email/text/validation.ctp:22 -msgid "Please copy the following address in your web browser {0}" -msgstr "Per favore copia il seguente indirizzo nel tuo browser web {0}" - -#: Template/Email/text/social_account_validation.ctp:24 -msgid "Please copy the following address in your web browser to activate your social login {0}" -msgstr "Per favore copia il seguente indirizzo nel tuo browser web per attivare il tuo login social {0}" - -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 Template/Users/index.ctp:13;26 -#: Template/Users/view.ctp:15;79 -msgid "Actions" -msgstr "Azioni" - -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 Template/Users/view.ctp:19 -msgid "List Users" -msgstr "Lista utenti" - -#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 Template/Users/view.ctp:21 -msgid "List Accounts" -msgstr "Lista Account" - -#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 -msgid "Add User" -msgstr "Aggiunti Utente" - -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 Template/Users/index.ctp:22 -#: Template/Users/profile.ctp:27 Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 -msgid "Username" -msgstr "Username" - -#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 Template/Users/index.ctp:23 -#: Template/Users/profile.ctp:29 Template/Users/register.ctp:19 Template/Users/view.ctp:32 -msgid "Email" -msgstr "Email" - -#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 Template/Users/index.ctp:24 -#: Template/Users/register.ctp:25 -msgid "First name" -msgstr "Nome" - -#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 Template/Users/index.ctp:25 -#: Template/Users/register.ctp:26 -msgid "Last name" -msgstr "Cognome" - -#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 Template/Users/view.ctp:44;75 -msgid "Active" -msgstr "Attivo" - -#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 Template/Users/edit.ctp:57 -#: Template/Users/register.ctp:35 Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 Template/Users/social_email.ctp:19 -msgid "Submit" -msgstr "Inviare" - -#: Template/Users/change_password.ctp:5 -msgid "Please enter the new password" -msgstr "Per favore inserire la nuova password" - -#: Template/Users/change_password.ctp:10 -msgid "Current password" -msgstr "Password attuale" - -#: Template/Users/change_password.ctp:16 -msgid "New password" -msgstr "Nuova password" - -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 -msgid "Confirm password" -msgstr "Conferma password" - -#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 Template/Users/view.ctp:101 -msgid "Delete" -msgstr "Cancellare" - -#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 Template/Users/view.ctp:18;101 -msgid "Are you sure you want to delete # {0}?" -msgstr "Sei sicuro di voler cancellare # {0} ?" - -#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 -msgid "Edit User" -msgstr "Modifica utente" - -#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 -msgid "Token" -msgstr "Token" - -#: Template/Users/edit.ctp:41 -msgid "Token expires" -msgstr "Scadenza Token" - -#: Template/Users/edit.ctp:44 -msgid "API token" -msgstr "API Token" - -#: Template/Users/edit.ctp:47 -msgid "Activation date" -msgstr "Data di attivazione" - -#: Template/Users/edit.ctp:50 -msgid "TOS date" -msgstr "Data TOS" - -#: Template/Users/index.ctp:15 -msgid "New {0}" -msgstr "Nuovo {0}" - -#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 -msgid "View" -msgstr "Vedere" - -#: Template/Users/index.ctp:38 -msgid "Change password" -msgstr "Cambiare la password" - -#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 -msgid "Edit" -msgstr "Modifier" - -#: Template/Users/index.ctp:49 -msgid "previous" -msgstr "precedente" - -#: Template/Users/index.ctp:51 -msgid "next" -msgstr "successivo" - -#: Template/Users/login.ctp:19 -msgid "Please enter your username and password" -msgstr "Per favore inserisci il tuo nome utente e la password" - -#: Template/Users/login.ctp:29 -msgid "Remember me" -msgstr "Ricordami" - -#: Template/Users/login.ctp:37 -msgid "Register" -msgstr "Iscriviti" - -#: Template/Users/login.ctp:43 -msgid "Reset Password" -msgstr "Ripristina Password" - -#: Template/Users/login.ctp:48 -msgid "Login" -msgstr "Login" - -#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 -msgid "{0} {1}" -msgstr "{0} {1}" - -#: Template/Users/profile.ctp:24 -msgid "Change Password" -msgstr "Cambiare Password" - -#: Template/Users/profile.ctp:34 -msgid "Social Accounts" -msgstr "Account Social" - -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 -msgid "Avatar" -msgstr "Foto profilo" - -#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 -msgid "Provider" -msgstr "Provider" - -#: Template/Users/profile.ctp:40 -msgid "Link" -msgstr "Link" - -#: Template/Users/profile.ctp:47 -msgid "Link to {0}" -msgstr "Link aĀ  {0}" - -#: Template/Users/register.ctp:20 -msgid "Password" -msgstr "Password" - -#: Template/Users/register.ctp:28 -msgid "Accept TOS conditions?" -msgstr "Accetti le condizioni TOS?" - -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" -msgstr "Per favore inserisci la tua email per ripristinare la password" - -#: Template/Users/resend_token_validation.ctp:15 -msgid "Resend Validation email" -msgstr "Rispedire Email di Convalidazione" - -#: Template/Users/resend_token_validation.ctp:17 -msgid "Email or username" -msgstr "Email o Username" - -#: Template/Users/view.ctp:18 -msgid "Delete User" -msgstr "Cancellare Utente" - -#: Template/Users/view.ctp:20 -msgid "New User" -msgstr "Nuovo Utente" - -#: Template/Users/view.ctp:28;67 -msgid "Id" -msgstr "Id" - -#: Template/Users/view.ctp:34 -msgid "First Name" -msgstr "Nome" - -#: Template/Users/view.ctp:36 -msgid "Last Name" -msgstr "Cognome" - -#: Template/Users/view.ctp:40 -msgid "Api Token" -msgstr "API Token" - -#: Template/Users/view.ctp:48;74 -msgid "Token Expires" -msgstr "Scadenza Token" - -#: Template/Users/view.ctp:50 -msgid "Activation Date" -msgstr "Data di attivazione" - -#: Template/Users/view.ctp:52 -msgid "Tos Date" -msgstr "Data Tos" - -#: Template/Users/view.ctp:54;77 -msgid "Created" -msgstr "Creato il" - -#: Template/Users/view.ctp:56;78 -msgid "Modified" -msgstr "Modificato il" - -#: Template/Users/view.ctp:63 -msgid "Related Accounts" -msgstr "Account correlati" - -#: Template/Users/view.ctp:68 -msgid "User Id" -msgstr "Id Utente" - -#: Template/Users/view.ctp:71 -msgid "Reference" -msgstr "Referenza" - -#: Template/Users/view.ctp:76 -msgid "Data" -msgstr "Dati" - -#: View/Helper/UserHelper.php:46 -msgid "Sign in with" -msgstr "Registrati con" - -#: View/Helper/UserHelper.php:49 -msgid "fa fa-{0}" -msgstr "fa fa-{0}" - -#: View/Helper/UserHelper.php:52 -msgid "btn btn-social btn-{0} " -msgstr "btn btn-social btn-{0} " - -#: View/Helper/UserHelper.php:91 -msgid "Logout" -msgstr "Logout" - -#: View/Helper/UserHelper.php:108 -msgid "Welcome, {0}" -msgstr "Benvenuto, {0}" - -#: View/Helper/UserHelper.php:131 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" -msgstr "reCaptcha non configurata! Per favore configura Users.reCaptcha.key" - -#: Model/Behavior/RegisterBehavior.php:148 -msgid "This field is required" -msgstr "Questo campo ĆØ obbligatorio" - -#~ msgid "The old password does not match" -#~ msgstr "La vecchia password non corrisponde" - -#~ msgid "" -#~ "If the link is not correctly displayed, please copy the following address in your web browser {0}" -#~ msgstr "" -#~ "Se il link non viene mostrato correttamente, per favore copiare il seguente indirizzonel tuo web " -#~ "browser {0}" diff --git a/src/Locale/pl/Users.mo b/src/Locale/pl/Users.mo deleted file mode 100644 index c5a1c88a33dc06eb0a6a1831ac6d7b562e8516b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14520 zcmb`Md6XqpeaB105eHDj5f?Nm5uF*FZh9IJ?3odoo*o#O&FStL#kKmq>h9`(ujX1z-7V+Cb%Ikh=@v18Dm@qqsbwJoaxpRjhg5&9?+9N)EpB%8keZYCCle~@2z@E z_dqbI)4%tvyVSkE``hmC-u~w^PkyJz^Ev2Q(6=AwdA|kUcPc+TH$BPoo&dfHJPUjW z_zdtU_y^!3I0SyzmDil%d5@=j0jPePz-NL};2(lDkgnd_9DV>?MfsE9Dd1G0LA{s6d|`Zs}31#flbqYgg< zYW@enlfW;4;`fW-YrwC8THggv@w~0z7^rz}0-p=M7d#)l9~2)y28X~^Fe$z-b~p-Z zJy(NT=N|BM@D-r=n+LVN1}J_Gf#-mS!Iyw{gI9pR0;QizS&Z;X@HFrxp!j+fsBvqc z*6~_Uj=o7_ZEI6w~x5;r$DuT5tKcB z9hCgO2Ws4(fU?h1FoqX^PXncoG0+E7Q1jgi%CGJN`NVq=lt26oTo0a3L2|qp6yICH z=Yi9p^nVj5y}Sn$A9sT4_eoIveFdBYzX^)}%P?-)$5r4aFb2;BkAnPpU*!i;dOrlU zj+0DbkGMkf@DE`0X$`69_r{99on-+;G zz0<+Vz_s8oI0woeZg==45LUe3f{4m{CWFhbF9u%s1Ro2&3zVGR3rfEq0_9KlgYSHd=lu()aSmYwu+mrK z>2(B@e_aM@{ZkH0pyYeN;p;)o|5i|PeK)9eA9dx2K+XRnQ0x8`D0^N5lN$GIhwDL_ zyo*7_lUIWJE^+NG@MOw2g3{N`;N!r%K+SuP!~4Khl)nnfF8;}te*jAVKLz>oPQ%Ew z{tG~TzYoOpya<&1ZvZ|Q1TmHXZ>>@ zDF6K%P;vSn96n~fmCG==lltA@Dc~IrKMZQ!p8&f!BSn$3I z%5HxLil1j-+~Ri_6hAKoWiN+7MD4u;RR6zr^$&s4&(A=u?>C^ne=0_>8r%d@*|33!B->*T%pEVa)`yK+HL^%L40q+1P zdEEiZejWhD&-X#e?{}c&w&p^M8$qpS7pV2V1=M$+2DPpSL9P4Ou6*`I)?PP(KJ~jm zmh2^<#{VFw`Tr7>oWBi<|9^GuKL@8MpZY?}e*nIS@-3kB@%Nzm{|r0}{7(>7cxx`U z@p~M63FY^Ln(rr|?C}(WtME)v-#-i739bbdzZ;Meule)myljJB1HBbG50an06OtTX59!%r!MhEVoX>#vKt6N? zN}yfPen`*9Efl|!ndI{7qQ>qoYbbx#)y+8kGw?3=F5i1MbS8Av)s?`TpwppwNcNy7 zv(WR48JN7{YFB$0-0t3Gf2hlQ8zkN9xeB_~ym{UZ@WarXU0HT;z`aW+H$a%Tu|HK0 zK#Hw@3bi0TAA;TwJy8Xo_d?S98=*U({CNj2AB8^YDio`(bnkxx-U97~E`zp0e*~Qb zy&c*B>A_XJ0J<4^2DB5>b1w8sNcQwxNO9$4=z1uBFiY=K&^>tt__40{I`7v&e*vxP zs;}}c`+hcb$km?%&O)DtJ_kJ=ilJlBYDj*g=Pl4F&}Qg%NO9*q&>utjGtEm48i8(f zl?`ws^g8Hn=qXSHT?AbV>G=rs0lo0t3ALdRS_|n>4EiASCg>GV|8pG`bA6SMrTki` z4806`8Z-{+xdIw9Z^TIOa`*mZunA2-3$E^c;6dmtXcDSG&w}0n?Ss}sdOo3_(LLM! zELjL+Z?sejYneZ}d%`azaXHGOBu+0?b<&74Kd98hpxp8g29>BBWMR2zp}kV}<0SK^ z!xfsNfX_%VtY?KS>Rg@lXNk>8o{{tWwVZBP@aCQ{Klnn&-@ma6&jeCEMT!?#-_@ zU>Ro&GGEhW{_sUF^rxdN_19f6>`%9{FkO%J$Fs#C^>8exWu>{Gs4+o7?s-09bPnTO zs;`d|bIw?y&%%$3{;oz|m9=W2w>?c8Vd`h~mIQ#+qVjGR6wx|EViqZ(^$ zb;*KhTnp3in{yFwrMa-QpplYh%q(+J%_kyMH9P^-_@Jin4-H@6H6lJZ+o%Vc&7WbI z5&s;bE|upq&0uY=cFrK4qG8M7Owg!c+nqtZok^LnhtKXJ0%>vPrEpx;<^^lps!>Sj zlq9KLxJ=N<=8}5U?lMjr7YPz+=IzO2Oa8)o6@+Xw4=NSoVrkK@r&;T^Gj_i2-Yncu zosZ{&6uV_}$S3L90rElIkk*re6vY$pjEu1WqYhJJwiOu#f+ZX`LTgtww<2G$LLnp3 z9^>tCjwx+g+xz{#e{_xwcSU$LUf;7dNk=(fk8a$qF9~^AUr-ptU_NBtAiG#rDRIiZ ze7xHT;)Ff=8l(&Di@BJ4XESRw_wI?L?lvVKuBy zBYU=vz1qRb{yv*L$?2^SRG)P=bX&~Vf+$GLFy9sPs}=h;aiDzZ<=&mn_Lq8!@s*Hu zT=+yC`qQix`W=jdo(1)&&SqG9m5}6at%*CqVPay3w#<5Xpb^zwWErhRSBEWsl<0(= zMkNy|y@_Zx&Nm2e!e((U(ihu~@u#rA^#nrf9V7K78q-x0l?f$vCZez_hvkv3ik^X7 zt8!+OCQh2Y0VSgbR%DE**z*bGQOu_7b`aBRgWps#kSjR6Hmk!wee$Spcbl1dQZ+G6 zG9tP3CJDkOO!3A5eVLnIPS{pu$<=^O-SjDxzJgKBhU{E2-a+4m8@6OWm<`x2HGYvD zbg|l#>#LIyS7#}-r@=wCsG`kfMNU6OwMe#*ppjgNgyEyuo^G;Y z2*+?1Rk%7J{3ync1qQ!3#5-p!{e?ru}N$0S0G+N*d+^NJO-n5V|Z_BJ~W-C}~Mz z`^g-Ui>POJc3A07LyLG0n>ml>z@;)L3!A{$Pu(2>Qy2FUVrea-cMmDU*NSy6p}FXr zZ{=F34wkmDP(yE&x0#MPM0B0*3)k&LbTfm?GjlhxPOC#B2}j2vT47cU(B=D4Je^!? z6dc8AR&ThQ88fh1>;KDe(^>381CCX_%7DF@0Ojh{i`g$d&in_Xq>*}^UCM@xWv~h*Q#0U1F@>!FjC_%!UJ#VNf0McZ}}3Vruk?aewpp&e82V zE*sstb?^AZ#EXl5BV1Cf-no6}c!%qagF~ywI7N|)4Je3@_!*)-lVLq&K|X8 zYI57aC7piaf%JJ`oKR8bBs=0?!X3nF!azN!3~Wp4)pW#bt$o7c@-F4XHfRS#|6IOJbkG-3cRaXapJd=Gz*pv zC;mK*ez1_Wnri1VP_IF0KJXXl$n{=CYRz3vQeHY7_-V9wo41Rqq#Os8u#Mgl*Rfn7 zzhi`1w*fc&h}$0wt>K3Q_Aaz<>YiCk^KS0Oe8F!VEd-V!D#cFHSJGXcWgd!f2$8c=5>MjeVD#*Hoi$=?0}-2;Ez;#EBK1!P7!L%#0j!y%{;|NwQ`X*2_zO zm5(x&u}`$ofVX=(EWx=OeXI1y4W~5OFU_g6v2+8w8^66`UZHBd+`^8y-xT!r9yc20 z1{nQ1^;%0pj#v!3l#x`ErTY*}v&EtVMAD3cazf?prO18c*@29eRgWK=T{>(nQ=QFM zsPFQ6u+VEs`B#<3G=gt8gO!-eO}sOZoy*;`!AJZ`VbzU}Y+D8p(L zJju@T`_QYxrQ0i!*|rSN^H>NIEZvT3GVUH*_)4uFG?BpuKV3*_5t7pcrM59FBJKhf zYu%z&Z-=uLCJ*X3sb)fG`Z~hb5{^*TqAw&jh z%p!1JO9`@?ufo}Uesd}tH+QGOeAZg;SxI!xMZN5Bvum<-3EetQT1%D=hoyFGGz!Cy z^nsC9C*WYEJ!@lzR*j&gf5ph1_qWn)@klLNI*eHB3AuK)<+qhqm{1m0{Wf05cyHs3m2-Okof;m)ijW*>5<5!6OwzyPe)#ubL^P z?}k=qZ&(q}ig&AGoqw|=RZOxH6S=xZC+Z~S)=XqJ0>nUM>z+&%MF{D7xBfy!pu5(f zD7K8q_P45>sEIv=R=g`aF)lXygAGe&am}=iQWqjIR)~24J2WA2S@*6!Zek*5fMCs# zD{fA9_T2f|=x_v$8#=x$|D)6V{~}pPmToAuTQ~>3f|%%Q$Hl3Peh9VvOKN`c2zo2E zGurJ==KbG3AM_?3O=RF-AaI*+mN09*PX_y_#xeTZWA;L;5$-rm$!t7%LGhG@c1zxu z%lCe=La$}6dY11>)m z&PW>O19)ggi$`#0J9|Lbs0G?f*g|NG`6miPXrHJ=^KNZ<-a^hnm@x@Cdxcw+3&lvp zgo`33+8Ep?ICs@yY`74nOYjJhRy^bh%cglGm+WQA^v3p9PEYz)VC3J<)u_PQiW{u2 z*U`GX-ey1j0nmEuloFpd|KO`2MoH4$qc%y?S4w%cfEBhCwgsb7lOK}&nSY!2_|Ay7hCC4}W8fItO1(_#x{fQ?_1>ttXmy*0 z;nP^=2ET3YT9r|lTUNKPcw5^T+CpQV-O;<8Eb~6LpgfRwl9aBzqMM~=%UqKZ-C@jZ z@Qp!#qEQKKi6NPA{YCZ5?0pyx2r-FvWW zFJ3VFXKvNXvgKYarLsELa8ujaPwd94%KYSlYUsYw%Csx1XJ7W&ncxH++CeQ!1AI#D z%h~F#ExPW}e+#V9vT}QPFuzpJ25I0N*%X!zcT2WyT(MhA{Cly^f3mW=zqWIKx_0H5 z_AqnUrkwv`nz&_TMUHZ!J#f&TwyepT6eYh9HF1JWu3+4aZyFNuhNR%|ZN6pT=dp>YW`MnOd@^Vga-G)>Qm+!wQPKQCA^t$?uI98U2m8njz zjx$>0w*u%sNp}xvq;sN1BjZOnZFkR{E4Wxi%SF~M?(#l_nf`7o2u40r9QL}WlI8b{ z!LGF3xiaWpsL`yl^WNOo((-;!&w>S}O!d$0dCtp;xe@42QrH!3zMGIgrwwk2(y+Rr zU{djsF1Z)x2OhhjDgo^TchZ^sY-)~0xGi@OlP1g46=6?iqYN&;n&1S10PiDmA30Gx z9z5ZWErTn(5d)JximW&eA30u4c4dc;da!hX1SDQSMoD=(O6sLH$;JQTE|+`D#oKCe z;OSm~j8r#p#olRjSgeV&sXg6Ep5b$Rl6zZbBbGrh_muwS@bK5WU25n_2tD~_SEF%p JbK}+W{s$j5;Di7G diff --git a/src/Locale/pl/Users.po b/src/Locale/pl/Users.po deleted file mode 100644 index 7c7834fe0..000000000 --- a/src/Locale/pl/Users.po +++ /dev/null @@ -1,811 +0,0 @@ -# LANGUAGE translation of CakePHP Application -# Copyright YEAR NAME -# -msgid "" -msgstr "" -"Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2017-07-02 20:08+0200\n" -"PO-Revision-Date: 2017-07-02 20:08+0200\n" -"Last-Translator: \n" -"Language-Team: LANGUAGE \n" -"Language: pl\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " -"|| n%100>=20) ? 1 : 2);\n" -"X-Generator: Poedit 2.0.1\n" - -#: Auth/ApiKeyAuthenticate.php:73 -msgid "Type {0} is not valid" -msgstr "Typ {0} jest nieprawidłowy" - -#: Auth/ApiKeyAuthenticate.php:77 -msgid "Type {0} has no associated callable" -msgstr "Brak callable dla typu {0}" - -#: Auth/ApiKeyAuthenticate.php:86 -msgid "SSL is required for ApiKey Authentication" -msgstr "Uwierzytelnienie ApiKey wymaga SSL" - -#: Auth/SimpleRbacAuthorize.php:142 -msgid "" -"Missing configuration file: \"config/{0}.php\". Using default permissions" -msgstr "" -"Brak pliku konfiguracji: \"config/{0}.php\". Użyto domyślnych uprawnień" - -#: Auth/SocialAuthenticate.php:432 -msgid "Provider cannot be empty" -msgstr "Dostawca nie może być pusty" - -#: Auth/Rules/AbstractRule.php:78 -msgid "" -"Table alias is empty, please define a table alias, we could not extract a " -"default table from the request" -msgstr "Alias tabeli jest pusty, zdefiniuj alias tabeli" - -#: Auth/Rules/Owner.php:67;70 -msgid "" -"Missing column {0} in table {1} while checking ownership permissions for " -"user {2}" -msgstr "" -"Nieistniejąca kolumna {0} w tabeli {0} podczas sprawdzania uprawnień dla " -"użytkownika {2}" - -#: Controller/SocialAccountsController.php:52 -msgid "Account validated successfully" -msgstr "Konto zostało aktywowane" - -#: Controller/SocialAccountsController.php:54 -msgid "Account could not be validated" -msgstr "Aktywacja konta nie powiodła się" - -#: Controller/SocialAccountsController.php:57 -msgid "Invalid token and/or social account" -msgstr "Nieprawidłowy token lub konto społecznościowe" - -#: Controller/SocialAccountsController.php:59;87 -msgid "Social Account already active" -msgstr "Konto społecznościowe jest już aktywne" - -#: Controller/SocialAccountsController.php:61 -msgid "Social Account could not be validated" -msgstr "Aktywacja nie powiodła się" - -#: Controller/SocialAccountsController.php:80 -msgid "Email sent successfully" -msgstr "E-mail został wysłany" - -#: Controller/SocialAccountsController.php:82 -msgid "Email could not be sent" -msgstr "E-mail nie mĆ³gł zostać wysłany" - -#: Controller/SocialAccountsController.php:85 -msgid "Invalid account" -msgstr "Nieprawidłowe konto" - -#: Controller/SocialAccountsController.php:89 -msgid "Email could not be resent" -msgstr "Nie można wysłać wiadomości e-mail" - -#: Controller/Component/RememberMeComponent.php:69 -msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" -msgstr "" -"Nieprawidłowa sĆ³l aplikacji, sĆ³l aplikacji powinna mieć długość co najmniej " -"256 bitĆ³w (32 bajty)" - -#: Controller/Component/UsersAuthComponent.php:178 -msgid "You can't enable email validation workflow if use_email is false" -msgstr "" -"Nie możesz włączyć potwierdzania kont przez e-mail jeśli opcja use_email = " -"false" - -#: Controller/Traits/LoginTrait.php:96 -msgid "Issues trying to log in with your social account" -msgstr "" -"Wystąpiły problemy z logowaniem za pośrednictwem konta społecznościowego" - -#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 -msgid "Please enter your email" -msgstr "Podaj swĆ³j adres e-mail" - -#: Controller/Traits/LoginTrait.php:108 -msgid "" -"Your user has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Twoje konto nie zostało jeszcze aktywowane. SprawdÅŗ swoją skrzynkę odbiorczą" - -#: Controller/Traits/LoginTrait.php:110 -msgid "" -"Your social account has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Konto społecznościowe nie zostało jeszcze aktywowane. SprawdÅŗ swoją pocztę e-" -"mail." - -#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 -msgid "Invalid reCaptcha" -msgstr "Błąd reCaptcha" - -#: Controller/Traits/LoginTrait.php:171 -msgid "You are already logged in" -msgstr "Jesteś już zalogowany" - -#: Controller/Traits/LoginTrait.php:217 -msgid "Username or password is incorrect" -msgstr "Nazwa użytkownika lub hasło jest nieprawidłowe" - -#: Controller/Traits/LoginTrait.php:238 -msgid "You've successfully logged out" -msgstr "Wylogowano" - -#: Controller/Traits/PasswordManagementTrait.php:47;76 -#: Controller/Traits/ProfileTrait.php:49 -msgid "User was not found" -msgstr "Konto użytkownika nie istnieje" - -#: Controller/Traits/PasswordManagementTrait.php:64;72;80 -msgid "Password could not be changed" -msgstr "Zmiana hasła nie powiodła się" - -#: Controller/Traits/PasswordManagementTrait.php:68 -msgid "Password has been changed successfully" -msgstr "Hasło zostało zmienione" - -#: Controller/Traits/PasswordManagementTrait.php:78 -msgid "{0}" -msgstr "{0}" - -#: Controller/Traits/PasswordManagementTrait.php:120 -msgid "Please check your email to continue with password reset process" -msgstr "Aby dokończyć zmianę hasła, sprawdÅŗ swoją pocztę e-mail." - -#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 -msgid "The password token could not be generated. Please try again" -msgstr "Nie można wygenerować tokenu. SprĆ³buj ponownie" - -#: Controller/Traits/PasswordManagementTrait.php:129 -#: Controller/Traits/UserValidationTrait.php:100 -msgid "User {0} was not found" -msgstr "Nie znaleziono użytkownika {0}" - -#: Controller/Traits/PasswordManagementTrait.php:131 -msgid "The user is not active" -msgstr "Konto użytkownika nie jest aktywne" - -#: Controller/Traits/PasswordManagementTrait.php:133 -#: Controller/Traits/UserValidationTrait.php:95;104 -msgid "Token could not be reset" -msgstr "Nie można zresetować tokenu" - -#: Controller/Traits/ProfileTrait.php:53 -msgid "Not authorized, please login first" -msgstr "Wymagane logowanie" - -#: Controller/Traits/RegisterTrait.php:42 -msgid "You must log out to register a new user account" -msgstr "Wyloguj się aby utworzyć nowe konto" - -#: Controller/Traits/RegisterTrait.php:88 -msgid "The user could not be saved" -msgstr "Nie można utworzyć konta" - -#: Controller/Traits/RegisterTrait.php:122 -msgid "You have registered successfully, please log in" -msgstr "Rejestracja zakończona sukcesem, możesz się zalogować" - -#: Controller/Traits/RegisterTrait.php:124 -msgid "Please validate your account before log in" -msgstr "PotwierdÅŗ swoje konto przed logowaniem" - -#: Controller/Traits/SimpleCrudTrait.php:76;106 -msgid "The {0} has been saved" -msgstr "{0} został zapisany" - -#: Controller/Traits/SimpleCrudTrait.php:80;110 -msgid "The {0} could not be saved" -msgstr "{0} nie mĆ³gł zostać zapisany" - -#: Controller/Traits/SimpleCrudTrait.php:130 -msgid "The {0} has been deleted" -msgstr "{0} został usunięty" - -#: Controller/Traits/SimpleCrudTrait.php:132 -msgid "The {0} could not be deleted" -msgstr "{0} nie mĆ³gł zostać usunięty" - -#: Controller/Traits/SocialTrait.php:39 -msgid "The reCaptcha could not be validated" -msgstr "Błąd walidacji reCaptcha" - -#: Controller/Traits/UserValidationTrait.php:42 -msgid "User account validated successfully" -msgstr "Konto użytkownika zostało aktywowane" - -#: Controller/Traits/UserValidationTrait.php:44 -msgid "User account could not be validated" -msgstr "Aktywacja konta nie powiodła się" - -#: Controller/Traits/UserValidationTrait.php:47 -msgid "User already active" -msgstr "Konto jest już aktywne" - -#: Controller/Traits/UserValidationTrait.php:53 -msgid "Reset password token was validated successfully" -msgstr "Token zmiany hasła został zatwierdzony" - -#: Controller/Traits/UserValidationTrait.php:58 -msgid "Reset password token could not be validated" -msgstr "Błąd podczas walidacji tokenu zmiany hasła" - -#: Controller/Traits/UserValidationTrait.php:62 -msgid "Invalid validation type" -msgstr "Nieprawidłowy typ walidacji" - -#: Controller/Traits/UserValidationTrait.php:65 -msgid "Invalid token or user account already validated" -msgstr "Nieprawidłowy token lub konto jest już aktywne" - -#: Controller/Traits/UserValidationTrait.php:67 -msgid "Token already expired" -msgstr "Token wygasł" - -#: Controller/Traits/UserValidationTrait.php:93 -msgid "Token has been reset successfully. Please check your email." -msgstr "Token został zresetowany. SprawdÅŗ swoją pocztę e-mail." - -#: Controller/Traits/UserValidationTrait.php:102 -msgid "User {0} is already active" -msgstr "Użytkownik {0} jest już aktywny" - -#: Email/EmailSender.php:39 -msgid "Your account validation link" -msgstr "TwĆ³j link aktywacyjny" - -#: Mailer/UsersMailer.php:55 -msgid "{0}Your reset password link" -msgstr "{0}TwĆ³j link zmiany hasła" - -#: Mailer/UsersMailer.php:78 -msgid "{0}Your social account validation link" -msgstr "{0} TwĆ³j link aktywacyjny" - -#: Model/Behavior/PasswordBehavior.php:56 -msgid "Reference cannot be null" -msgstr "Wartość nie może być pusta" - -#: Model/Behavior/PasswordBehavior.php:61 -msgid "Token expiration cannot be empty" -msgstr "Parametr 'expiration' nie może być pusty" - -#: Model/Behavior/PasswordBehavior.php:67;116 -msgid "User not found" -msgstr "Nie odnaleziono użytkownika" - -#: Model/Behavior/PasswordBehavior.php:71 -#: Model/Behavior/RegisterBehavior.php:111 -msgid "User account already validated" -msgstr "Konto użytkownika zostało już aktywowane" - -#: Model/Behavior/PasswordBehavior.php:78 -msgid "User not active" -msgstr "Użytkownik nie jest aktywny" - -#: Model/Behavior/PasswordBehavior.php:121 -msgid "The current password does not match" -msgstr "Bieżące hasło nie jest prawidłowe" - -#: Model/Behavior/PasswordBehavior.php:124 -msgid "You cannot use the current password as the new one" -msgstr "Nowe hasło nie może być takie same jak obecne" - -#: Model/Behavior/RegisterBehavior.php:89 -msgid "User not found for the given token and email." -msgstr "Nie odnaleziono użytkownika dla danego tokenu i adresu e-mail." - -#: Model/Behavior/RegisterBehavior.php:92 -msgid "Token has already expired user with no token" -msgstr "Token wygasł" - -#: Model/Behavior/SocialAccountBehavior.php:102;129 -msgid "Account already validated" -msgstr "Konto zostało już aktywowane" - -#: Model/Behavior/SocialAccountBehavior.php:105;132 -msgid "Account not found for the given token and email." -msgstr "Nie odnaleziono konta dla danego tokenu i adresu e-mail." - -#: Model/Behavior/SocialBehavior.php:56 -msgid "Unable to login user with reference {0}" -msgstr "Nie można zalogować użytkownika o loginie {0}" - -#: Model/Behavior/SocialBehavior.php:98 -msgid "Email not present" -msgstr "Brak adresu e-mail" - -#: Model/Table/UsersTable.php:82 -msgid "Your password does not match your confirm password. Please try again" -msgstr "Podane hasła rĆ³Å¼nią się. SprĆ³buj ponownie." - -#: Model/Table/UsersTable.php:175 -msgid "Username already exists" -msgstr "Nazwa użytkownika już istnieje" - -#: Model/Table/UsersTable.php:181 -msgid "Email already exists" -msgstr "Adres e-mail już istnieje" - -#: Model/Table/UsersTable.php:214 -msgid "Missing 'username' in options data" -msgstr "Brak klucza 'username'" - -#: Shell/UsersShell.php:54 -msgid "Utilities for CakeDC Users Plugin" -msgstr "Narzędzia dla CakeDC Users Plugin" - -#: Shell/UsersShell.php:55 -msgid "Activate an specific user" -msgstr "Aktywuj użytkownika" - -#: Shell/UsersShell.php:56 -msgid "Add a new superadmin user for testing purposes" -msgstr "Dodaj konto administracyjne do celĆ³w testowych" - -#: Shell/UsersShell.php:57 -msgid "Add a new user" -msgstr "Dodaj użytkownika" - -#: Shell/UsersShell.php:58 -msgid "Change the role for an specific user" -msgstr "Zmień rolę konkretnego użytkownika" - -#: Shell/UsersShell.php:59 -msgid "Deactivate an specific user" -msgstr "Deaktywuj użytkownika" - -#: Shell/UsersShell.php:60 -msgid "Delete an specific user" -msgstr "Usuń użytkownika" - -#: Shell/UsersShell.php:61 -msgid "Reset the password via email" -msgstr "Zresetuj hasło przez e-mail" - -#: Shell/UsersShell.php:62 -msgid "Reset the password for all users" -msgstr "Zresetuj hasło dla wszystkich użytkownikĆ³w" - -#: Shell/UsersShell.php:63 -msgid "Reset the password for an specific user" -msgstr "Zresetuj hasło dla konkretnego użytkownika" - -#: Shell/UsersShell.php:98 -msgid "User added:" -msgstr "Dodano użytkownika:" - -#: Shell/UsersShell.php:99;127 -msgid "Id: {0}" -msgstr "Id: {0}" - -#: Shell/UsersShell.php:100;128 -msgid "Username: {0}" -msgstr "Nazwa użytkownika: {0}" - -#: Shell/UsersShell.php:101;129 -msgid "Email: {0}" -msgstr "E-mail: {0}" - -#: Shell/UsersShell.php:102;130 -msgid "Password: {0}" -msgstr "Hasło: {0}" - -#: Shell/UsersShell.php:126 -msgid "Superuser added:" -msgstr "Dodano super użytkownika:" - -#: Shell/UsersShell.php:132 -msgid "Superuser could not be added:" -msgstr "Nie można dodać super użytkownika:" - -#: Shell/UsersShell.php:135 -msgid "Field: {0} Error: {1}" -msgstr "Pole: {0} Błąd: {1}" - -#: Shell/UsersShell.php:153;179 -msgid "Please enter a password." -msgstr "Podaj hasło." - -#: Shell/UsersShell.php:157 -msgid "Password changed for all users" -msgstr "Zmieniono hasło dla wszystkich użytkownikĆ³w" - -#: Shell/UsersShell.php:158;186 -msgid "New password: {0}" -msgstr "Nowe hasło: {0}" - -#: Shell/UsersShell.php:176;204;282;324 -msgid "Please enter a username." -msgstr "Podaj nazwę użytkownika." - -#: Shell/UsersShell.php:185 -msgid "Password changed for user: {0}" -msgstr "Zmieniono hasło dla użytkownika: {0}" - -#: Shell/UsersShell.php:207 -msgid "Please enter a role." -msgstr "Podaj rolę." - -#: Shell/UsersShell.php:213 -msgid "Role changed for user: {0}" -msgstr "Zmieniono rolę dla użytkownika: {0}" - -#: Shell/UsersShell.php:214 -msgid "New role: {0}" -msgstr "Nowa rola: {0}" - -#: Shell/UsersShell.php:229 -msgid "User was activated: {0}" -msgstr "Użytkownik został aktywowany: {0}" - -#: Shell/UsersShell.php:244 -msgid "User was de-activated: {0}" -msgstr "Użytkownik został zdeaktywowany: {0}" - -#: Shell/UsersShell.php:256 -msgid "Please enter a username or email." -msgstr "Podaj nazwę użytkownika lub hasło." - -#: Shell/UsersShell.php:264 -msgid "" -"Please ask the user to check the email to continue with password reset " -"process" -msgstr "Aby dokończyć zmianę hasła, sprawdÅŗ swoją pocztę e-mail" - -#: Shell/UsersShell.php:302 -msgid "The user was not found." -msgstr "Nie odnaleziono użytkownika." - -#: Shell/UsersShell.php:332 -msgid "The user {0} was not deleted. Please try again" -msgstr "Usuwanie użytkownika {0} nie powiodło się. SprĆ³buj ponownie" - -#: Shell/UsersShell.php:334 -msgid "The user {0} was deleted successfully" -msgstr "Użytkownik {0} został usunięty" - -#: Template/Email/html/reset_password.ctp:21 -#: Template/Email/html/social_account_validation.ctp:14 -#: Template/Email/html/validation.ctp:21 -#: Template/Email/text/reset_password.ctp:20 -#: Template/Email/text/social_account_validation.ctp:22 -#: Template/Email/text/validation.ctp:20 -msgid "Hi {0}" -msgstr "Witaj {0}" - -#: Template/Email/html/reset_password.ctp:24 -msgid "Reset your password here" -msgstr "Kontynuuj zmianę hasła" - -#: Template/Email/html/reset_password.ctp:27 -#: Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 -msgid "" -"If the link is not correcly displayed, please copy the following address in " -"your web browser {0}" -msgstr "" -"Jeśli link nie jest wyświetlony poprawnie, skopiuj łącze do paska adresu " -"przeglądarki {0}" - -#: Template/Email/html/reset_password.ctp:30 -#: Template/Email/html/social_account_validation.ctp:35 -#: Template/Email/html/validation.ctp:30 -#: Template/Email/text/reset_password.ctp:24 -#: Template/Email/text/social_account_validation.ctp:26 -#: Template/Email/text/validation.ctp:24 -msgid "Thank you" -msgstr "Dziękujemy" - -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" -msgstr "Aktywuj konto" - -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" -msgstr "Aktywuj konto" - -#: Template/Email/text/reset_password.ctp:22 -#: Template/Email/text/validation.ctp:22 -msgid "Please copy the following address in your web browser {0}" -msgstr "Skopiuj łącze do paska adresu przeglądarki {0}" - -#: Template/Email/text/social_account_validation.ctp:24 -msgid "" -"Please copy the following address in your web browser to activate your " -"social login {0}" -msgstr "Skopiuj łącze do paska adresu przeglądarki, aby aktywować konto {0}" - -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 -msgid "Actions" -msgstr "Akcje" - -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 -#: Template/Users/view.ctp:19 -msgid "List Users" -msgstr "Użytkownicy" - -#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:21 -msgid "List Accounts" -msgstr "Konta" - -#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 -msgid "Add User" -msgstr "Dodaj użytkownika" - -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 -#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 -#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 -msgid "Username" -msgstr "Nazwa użytkownika" - -#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 -#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 -msgid "Email" -msgstr "E-mail" - -#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 -msgid "First name" -msgstr "Imię" - -#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 -msgid "Last name" -msgstr "Nazwisko" - -#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:44;75 -msgid "Active" -msgstr "Aktywny" - -#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 -#: Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:19 -msgid "Submit" -msgstr "Wyślij" - -#: Template/Users/change_password.ctp:5 -msgid "Please enter the new password" -msgstr "Podaj nowe hasło" - -#: Template/Users/change_password.ctp:10 -msgid "Current password" -msgstr "Obecne hasło" - -#: Template/Users/change_password.ctp:16 -msgid "New password" -msgstr "Nowe hasło" - -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 -msgid "Confirm password" -msgstr "PotwierdÅŗ hasło" - -#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:101 -msgid "Delete" -msgstr "Usuń" - -#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:18;101 -msgid "Are you sure you want to delete # {0}?" -msgstr "Czy na pewno usunąć # {0}?" - -#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 -msgid "Edit User" -msgstr "Edytuj użytkownika" - -#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 -msgid "Token" -msgstr "Token" - -#: Template/Users/edit.ctp:41 -msgid "Token expires" -msgstr "Token wygasa" - -#: Template/Users/edit.ctp:44 -msgid "API token" -msgstr "API token" - -#: Template/Users/edit.ctp:47 -msgid "Activation date" -msgstr "Data aktywacji" - -#: Template/Users/edit.ctp:50 -msgid "TOS date" -msgstr "Data (TOS)" - -#: Template/Users/index.ctp:15 -msgid "New {0}" -msgstr "Nowy {0}" - -#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 -msgid "View" -msgstr "SzczegĆ³Å‚y" - -#: Template/Users/index.ctp:38 -msgid "Change password" -msgstr "Zmień hasło" - -#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 -msgid "Edit" -msgstr "Edytuj" - -#: Template/Users/index.ctp:49 -msgid "previous" -msgstr "poprzednia" - -#: Template/Users/index.ctp:51 -msgid "next" -msgstr "następna" - -#: Template/Users/login.ctp:19 -msgid "Please enter your username and password" -msgstr "Podaj nazwę użytkownika i hasło" - -#: Template/Users/login.ctp:29 -msgid "Remember me" -msgstr "Zapamiętaj" - -#: Template/Users/login.ctp:37 -msgid "Register" -msgstr "Rejestracja" - -#: Template/Users/login.ctp:43 -msgid "Reset Password" -msgstr "Zresetuj hasło" - -#: Template/Users/login.ctp:48 -msgid "Login" -msgstr "Zaloguj" - -#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 -msgid "{0} {1}" -msgstr "{0} {1}" - -#: Template/Users/profile.ctp:24 -msgid "Change Password" -msgstr "Zmień hasło" - -#: Template/Users/profile.ctp:34 -msgid "Social Accounts" -msgstr "Konta społecznościowe" - -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 -msgid "Avatar" -msgstr "Avatar" - -#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 -msgid "Provider" -msgstr "Dostawca" - -#: Template/Users/profile.ctp:40 -msgid "Link" -msgstr "Link" - -#: Template/Users/profile.ctp:47 -msgid "Link to {0}" -msgstr "Link do {0}" - -#: Template/Users/register.ctp:20 -msgid "Password" -msgstr "Hasło" - -#: Template/Users/register.ctp:28 -msgid "Accept TOS conditions?" -msgstr "Akceptuję warunki użytkowania" - -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" -msgstr "W celu zmiany hasła podaj adres e-mail" - -#: Template/Users/resend_token_validation.ctp:15 -msgid "Resend Validation email" -msgstr "Ponownie wyślij e-mail aktywacyjny" - -#: Template/Users/resend_token_validation.ctp:17 -msgid "Email or username" -msgstr "E-mail lub nazwa użytkownika" - -#: Template/Users/view.ctp:18 -msgid "Delete User" -msgstr "Usuń użytkownika" - -#: Template/Users/view.ctp:20 -msgid "New User" -msgstr "Nowy użytkownik" - -#: Template/Users/view.ctp:28;67 -msgid "Id" -msgstr "Id" - -#: Template/Users/view.ctp:34 -msgid "First Name" -msgstr "Imię" - -#: Template/Users/view.ctp:36 -msgid "Last Name" -msgstr "Nazwisko" - -#: Template/Users/view.ctp:40 -msgid "Api Token" -msgstr "Api Token" - -#: Template/Users/view.ctp:48;74 -msgid "Token Expires" -msgstr "Token wygasa" - -#: Template/Users/view.ctp:50 -msgid "Activation Date" -msgstr "Data aktywacji" - -#: Template/Users/view.ctp:52 -msgid "Tos Date" -msgstr "Data (TOS)" - -#: Template/Users/view.ctp:54;77 -msgid "Created" -msgstr "Utworzono" - -#: Template/Users/view.ctp:56;78 -msgid "Modified" -msgstr "Zmodyfikowano" - -#: Template/Users/view.ctp:63 -msgid "Related Accounts" -msgstr "Powiązane konta" - -#: Template/Users/view.ctp:68 -msgid "User Id" -msgstr "Id użytkownika" - -#: Template/Users/view.ctp:71 -msgid "Reference" -msgstr "Reference" - -#: Template/Users/view.ctp:76 -msgid "Data" -msgstr "Dane" - -#: View/Helper/UserHelper.php:46 -msgid "Sign in with" -msgstr "Zaloguj się za pomocą" - -#: View/Helper/UserHelper.php:49 -msgid "fa fa-{0}" -msgstr "fa fa-{0}" - -#: View/Helper/UserHelper.php:52 -msgid "btn btn-social btn-{0} " -msgstr "btn btn-social btn-{0} " - -#: View/Helper/UserHelper.php:91 -msgid "Logout" -msgstr "Wyloguj" - -#: View/Helper/UserHelper.php:108 -msgid "Welcome, {0}" -msgstr "Witaj, {0}" - -#: View/Helper/UserHelper.php:131 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" -msgstr "" -"reCaptcha nie zostało skonfigurowane! Skonfiguruj opcję Users.reCaptcha.key" - -#: Model/Behavior/RegisterBehavior.php:148 -msgid "This field is required" -msgstr "Pole wymagane" diff --git a/src/Locale/pt_BR/Users.mo b/src/Locale/pt_BR/Users.mo deleted file mode 100644 index 5cbc087b8fb6ad1fc6defdce71a871a71909e486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15088 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\n" -"Language-Team: CakeDC \n" -"Language: pt_BR\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 2.0.4\n" - -#: Auth/SocialAuthenticate.php:456 -msgid "Provider cannot be empty" -msgstr "O provedor nĆ£o pode ser vazio" - -#: Controller/SocialAccountsController.php:52 -msgid "Account validated successfully" -msgstr "Conta validada com ĆŖxito" - -#: Controller/SocialAccountsController.php:54 -msgid "Account could not be validated" -msgstr "A conta nĆ£o pode ser validada" - -#: Controller/SocialAccountsController.php:57 -msgid "Invalid token and/or social account" -msgstr "Token e/ou conta social invĆ”lido(s)" - -#: Controller/SocialAccountsController.php:59;87 -msgid "Social Account already active" -msgstr "Conta social jĆ” ativa" - -#: Controller/SocialAccountsController.php:61 -msgid "Social Account could not be validated" -msgstr "A conta social nĆ£o pode ser validada" - -#: Controller/SocialAccountsController.php:80 -msgid "Email sent successfully" -msgstr "Email enviado com sucesso" - -#: Controller/SocialAccountsController.php:82 -msgid "Email could not be sent" -msgstr "O email nĆ£o pode ser enviado" - -#: Controller/SocialAccountsController.php:85 -msgid "Invalid account" -msgstr "Conta invĆ”lida" - -#: Controller/SocialAccountsController.php:89 -msgid "Email could not be resent" -msgstr "O email nĆ£o pode ser reenviado" - -#: Controller/Component/RememberMeComponent.php:68 -msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" -msgstr "" -"Salt da aplicaĆ§Ć£o invĆ”lido, o salt da aplicaĆ§Ć£o deve ser de pelo menos 256 " -"bits (32 bytes)" - -#: Controller/Component/UsersAuthComponent.php:204 -msgid "You can't enable email validation workflow if use_email is false" -msgstr "" -"VocĆŖ nĆ£o pode habilitar o fluxo de validaĆ§Ć£o por email se use_email for false" - -#: Controller/Traits/LinkSocialTrait.php:54 -msgid "Could not associate account, please try again." -msgstr "NĆ£o foi possĆ­vel associar a conta, tente novamente." - -#: Controller/Traits/LinkSocialTrait.php:77 -msgid "Social account was associated." -msgstr "A conta social foi associada." - -#: Controller/Traits/LoginTrait.php:104 -msgid "Issues trying to log in with your social account" -msgstr "Problemas ao tentar autenticar a partir da sua conta social" - -#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 -msgid "Please enter your email" -msgstr "Por favor indique seu email" - -#: Controller/Traits/LoginTrait.php:120 -msgid "" -"Your user has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Seu usuĆ”rio ainda nĆ£o foi validado. Por favor, verifique sua caixa de " -"entrada para instruƧƵes" - -#: Controller/Traits/LoginTrait.php:125 -msgid "" -"Your social account has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Sua conta social ainda nĆ£o foi validada. Por favor, verifique sua caixa de " -"entrada para instruƧƵes" - -#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 -msgid "Invalid reCaptcha" -msgstr "ReCaptcha invĆ”lido" - -#: Controller/Traits/LoginTrait.php:191 -msgid "You are already logged in" -msgstr "VocĆŖ jĆ” estĆ” autenticado" - -#: Controller/Traits/LoginTrait.php:212 -msgid "Please enable Google Authenticator first." -msgstr "Por favor habilite o Google Authenticator primeiro." - -#: Controller/Traits/LoginTrait.php:287 -msgid "Verification code is invalid. Try again" -msgstr "CĆ³digo de verificaĆ§Ć£o Ć© invĆ”lido. Tente novamente" - -#: Controller/Traits/LoginTrait.php:340 -msgid "Username or password is incorrect" -msgstr "Nome de usuĆ”rio e/ou senha incorreto(s)" - -#: Controller/Traits/LoginTrait.php:363 -msgid "You've successfully logged out" -msgstr "VocĆŖ desconectou-se com ĆŖxito" - -#: Controller/Traits/PasswordManagementTrait.php:49;82 -#: Controller/Traits/ProfileTrait.php:50 -msgid "User was not found" -msgstr "O usuĆ”rio nĆ£o foi encontrado" - -#: Controller/Traits/PasswordManagementTrait.php:70;78;86 -msgid "Password could not be changed" -msgstr "A senha nĆ£o pode ser alterada" - -#: Controller/Traits/PasswordManagementTrait.php:74 -msgid "Password has been changed successfully" -msgstr "Senha alterada com ĆŖxito" - -#: Controller/Traits/PasswordManagementTrait.php:84 -msgid "{0}" -msgstr "{0}" - -#: Controller/Traits/PasswordManagementTrait.php:127 -msgid "Please check your email to continue with password reset process" -msgstr "" -"Por favor, verifique seu email para continuar o processo de redefiniĆ§Ć£o de " -"senha" - -#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 -msgid "The password token could not be generated. Please try again" -msgstr "O token de senha nĆ£o pode ser gerado. Por favor, tente novamente" - -#: Controller/Traits/PasswordManagementTrait.php:136 -#: Controller/Traits/UserValidationTrait.php:107 -msgid "User {0} was not found" -msgstr "O usuĆ”rio {0} nĆ£o foi encontrado" - -#: Controller/Traits/PasswordManagementTrait.php:138 -msgid "The user is not active" -msgstr "O usuĆ”rio nĆ£o estĆ” ativo" - -#: Controller/Traits/PasswordManagementTrait.php:140 -#: Controller/Traits/UserValidationTrait.php:102;111 -msgid "Token could not be reset" -msgstr "O token nĆ£o pode ser redefinido" - -#: Controller/Traits/PasswordManagementTrait.php:164 -msgid "Google Authenticator token was successfully reset" -msgstr "O token do Google Authenticator foi reiniciado com sucesso" - -#: Controller/Traits/ProfileTrait.php:54 -msgid "Not authorized, please login first" -msgstr "NĆ£o autorizado, por favor, autentique-se primeiro" - -#: Controller/Traits/RegisterTrait.php:43 -msgid "You must log out to register a new user account" -msgstr "VocĆŖ deve deslogar para registrar uma nova conta de usuĆ”rio" - -#: Controller/Traits/RegisterTrait.php:89 -msgid "The user could not be saved" -msgstr "O usuĆ”rio nĆ£o pode ser salvo" - -#: Controller/Traits/RegisterTrait.php:123 -msgid "You have registered successfully, please log in" -msgstr "VocĆŖ registrou-se com sucesso, por favor, autentique-se" - -#: Controller/Traits/RegisterTrait.php:125 -msgid "Please validate your account before log in" -msgstr "Por favor, valide sua conta antes de autenticar" - -#: Controller/Traits/SimpleCrudTrait.php:77;107 -msgid "The {0} has been saved" -msgstr "O {0} foi salvo" - -#: Controller/Traits/SimpleCrudTrait.php:81;111 -msgid "The {0} could not be saved" -msgstr "O {0} nĆ£o pode ser salvo" - -#: Controller/Traits/SimpleCrudTrait.php:131 -msgid "The {0} has been deleted" -msgstr "O {0} foi deletado" - -#: Controller/Traits/SimpleCrudTrait.php:133 -msgid "The {0} could not be deleted" -msgstr "O {0} nĆ£o pode ser deletado" - -#: Controller/Traits/SocialTrait.php:40 -msgid "The reCaptcha could not be validated" -msgstr "O reCaptcha nĆ£o pode ser validado" - -#: Controller/Traits/UserValidationTrait.php:43 -msgid "User account validated successfully" -msgstr "Conta de usuĆ”rio validada com ĆŖxito" - -#: Controller/Traits/UserValidationTrait.php:45 -msgid "User account could not be validated" -msgstr "A conta de usuĆ”rio nĆ£o pode ser validada" - -#: Controller/Traits/UserValidationTrait.php:48 -msgid "User already active" -msgstr "UsuĆ”rio jĆ” ativo" - -#: Controller/Traits/UserValidationTrait.php:54 -msgid "Reset password token was validated successfully" -msgstr "Token de redefiniĆ§Ć£o de senha validado com ĆŖxito" - -#: Controller/Traits/UserValidationTrait.php:62 -msgid "Reset password token could not be validated" -msgstr "O token de redefiniĆ§Ć£o de senha nĆ£o pode ser validado" - -#: Controller/Traits/UserValidationTrait.php:66 -msgid "Invalid validation type" -msgstr "Tipo de validaĆ§Ć£o invĆ”lido" - -#: Controller/Traits/UserValidationTrait.php:69 -msgid "Invalid token or user account already validated" -msgstr "Token invĆ”lido ou conta jĆ” validada" - -#: Controller/Traits/UserValidationTrait.php:71 -msgid "Token already expired" -msgstr "Token expirado" - -#: Controller/Traits/UserValidationTrait.php:97 -msgid "Token has been reset successfully. Please check your email." -msgstr "O token foi redefinido com ĆŖxito. Por favor, verifique seu email." - -#: Controller/Traits/UserValidationTrait.php:109 -msgid "User {0} is already active" -msgstr "O usuĆ”rio {0} jĆ” estĆ” ativo" - -#: Mailer/UsersMailer.php:34 -msgid "Your account validation link" -msgstr "Seu link de validaĆ§Ć£o da conta" - -#: Mailer/UsersMailer.php:52 -msgid "{0}Your reset password link" -msgstr "{0}Seu link de redefiniĆ§Ć£o de senha" - -#: Mailer/UsersMailer.php:75 -msgid "{0}Your social account validation link" -msgstr "{0}Seu link de validaĆ§Ć£o da conta social" - -#: Model/Behavior/AuthFinderBehavior.php:49 -msgid "Missing 'username' in options data" -msgstr "'username' ausente nas opƧƵes" - -#: Model/Behavior/LinkSocialBehavior.php:53 -msgid "Social account already associated to another user" -msgstr "Conta social jĆ” estĆ” associada a outro usuĆ”rio" - -#: Model/Behavior/PasswordBehavior.php:45 -msgid "Reference cannot be null" -msgstr "A referĆŖncia nĆ£o pode ser nula" - -#: Model/Behavior/PasswordBehavior.php:50 -msgid "Token expiration cannot be empty" -msgstr "A expiraĆ§Ć£o do token nĆ£o pode ser vazia" - -#: Model/Behavior/PasswordBehavior.php:56;117 -msgid "User not found" -msgstr "UsuĆ”rio nĆ£o encontrado" - -#: Model/Behavior/PasswordBehavior.php:60 -#: Model/Behavior/RegisterBehavior.php:112;205 -msgid "User account already validated" -msgstr "Conta de usuĆ”rio jĆ” validada" - -#: Model/Behavior/PasswordBehavior.php:67 -msgid "User not active" -msgstr "UsuĆ”rio inativo" - -#: Model/Behavior/PasswordBehavior.php:122 -msgid "The current password does not match" -msgstr "A senha atual nĆ£o corresponde" - -#: Model/Behavior/PasswordBehavior.php:125 -msgid "You cannot use the current password as the new one" -msgstr "VocĆŖ nĆ£o pode usar a senha atual como nova senha" - -#: Model/Behavior/RegisterBehavior.php:90 -msgid "User not found for the given token and email." -msgstr "UsuĆ”rio nĆ£o encontrado com a combinaĆ§Ć£o de token e email" - -#: Model/Behavior/RegisterBehavior.php:93 -msgid "Token has already expired user with no token" -msgstr "Token expirado, usuĆ”rio sem token" - -#: Model/Behavior/SocialAccountBehavior.php:103;130 -msgid "Account already validated" -msgstr "Conta jĆ” validada" - -#: Model/Behavior/SocialAccountBehavior.php:106;133 -msgid "Account not found for the given token and email." -msgstr "Conta nĆ£o encontrada com a combinaĆ§Ć£o de token e email" - -#: Model/Behavior/SocialBehavior.php:82 -msgid "Unable to login user with reference {0}" -msgstr "Incapaz de autenticar usuĆ”rio com a referĆŖncia {0}" - -#: Model/Behavior/SocialBehavior.php:121 -msgid "Email not present" -msgstr "Email ausente" - -#: Model/Table/UsersTable.php:81 -msgid "Your password does not match your confirm password. Please try again" -msgstr "" -"Sua senha nĆ£o corresponde com a confirmaĆ§Ć£o. Por favor, tente novamente" - -#: Model/Table/UsersTable.php:173 -msgid "Username already exists" -msgstr "Nome de usuĆ”rio em uso" - -#: Model/Table/UsersTable.php:179 -msgid "Email already exists" -msgstr "Email em uso" - -#: Shell/UsersShell.php:58 -msgid "Utilities for CakeDC Users Plugin" -msgstr "UtilitĆ”rios para CakeDC Users Plugin" - -#: Shell/UsersShell.php:60 -msgid "Activate an specific user" -msgstr "Ativar um usuĆ”rio especĆ­fico" - -#: Shell/UsersShell.php:63 -msgid "Add a new superadmin user for testing purposes" -msgstr "Adicionar um novo usuĆ”rio superadmin para fins de testes" - -#: Shell/UsersShell.php:66 -msgid "Add a new user" -msgstr "Adicionar um novo usuĆ”rio" - -#: Shell/UsersShell.php:69 -msgid "Change the role for an specific user" -msgstr "Alterar o role de um usuĆ”rio especĆ­fico" - -#: Shell/UsersShell.php:72 -msgid "Deactivate an specific user" -msgstr "Desativar um usuĆ”rio especĆ­fico" - -#: Shell/UsersShell.php:75 -msgid "Delete an specific user" -msgstr "Deletar um usuĆ”rio especĆ­fico" - -#: Shell/UsersShell.php:78 -msgid "Reset the password via email" -msgstr "Redefinir a senha via email" - -#: Shell/UsersShell.php:81 -msgid "Reset the password for all users" -msgstr "Redefinir a senha de todos usuĆ”rios" - -#: Shell/UsersShell.php:84 -msgid "Reset the password for an specific user" -msgstr "Redefinir a senha de um usuĆ”rio especĆ­fico" - -#: Shell/UsersShell.php:133;159 -msgid "Please enter a password." -msgstr "Por favor, indique uma senha." - -#: Shell/UsersShell.php:137 -msgid "Password changed for all users" -msgstr "As senhas de todos usuĆ”rios foram alteradas" - -#: Shell/UsersShell.php:138;166 -msgid "New password: {0}" -msgstr "Nova senha: {0}" - -#: Shell/UsersShell.php:156;184;262;359 -msgid "Please enter a username." -msgstr "Por favor, indique um nome de usuĆ”rio." - -#: Shell/UsersShell.php:165 -msgid "Password changed for user: {0}" -msgstr "Senha alterada para usuĆ”rio: {0}" - -#: Shell/UsersShell.php:187 -msgid "Please enter a role." -msgstr "Por favor, indique um papel." - -#: Shell/UsersShell.php:193 -msgid "Role changed for user: {0}" -msgstr "Papel alterado para usuĆ”rio: {0}" - -#: Shell/UsersShell.php:194 -msgid "New role: {0}" -msgstr "Novo papel: {0}" - -#: Shell/UsersShell.php:209 -msgid "User was activated: {0}" -msgstr "UsuĆ”rio ativado: {0}" - -#: Shell/UsersShell.php:224 -msgid "User was de-activated: {0}" -msgstr "UsuĆ”rio desativado: {0}" - -#: Shell/UsersShell.php:236 -msgid "Please enter a username or email." -msgstr "Por favor, indique um nome de usuĆ”rio ou senha." - -#: Shell/UsersShell.php:244 -msgid "" -"Please ask the user to check the email to continue with password reset " -"process" -msgstr "" -"Por favor, peƧa ao usuĆ”rio para verificar seu email para continuar o " -"processo de redefiniĆ§Ć£o de senha" - -#: Shell/UsersShell.php:308 -msgid "Superuser added:" -msgstr "SuperusuĆ”rio adicionado:" - -#: Shell/UsersShell.php:310 -msgid "User added:" -msgstr "UsuĆ”rio adicionado:" - -#: Shell/UsersShell.php:312 -msgid "Id: {0}" -msgstr "Id: {0}" - -#: Shell/UsersShell.php:313 -msgid "Username: {0}" -msgstr "Nome de usuĆ”rio: {0}" - -#: Shell/UsersShell.php:314 -msgid "Email: {0}" -msgstr "Email: {0}" - -#: Shell/UsersShell.php:315 -msgid "Role: {0}" -msgstr "Papel: {0}" - -#: Shell/UsersShell.php:316 -msgid "Password: {0}" -msgstr "Senha: {0}" - -#: Shell/UsersShell.php:318 -msgid "User could not be added:" -msgstr "UsuĆ”rio nĆ£o pĆ“de ser adicionado:" - -#: Shell/UsersShell.php:321 -msgid "Field: {0} Error: {1}" -msgstr "Campo: {0} Erro: {1}" - -#: Shell/UsersShell.php:337 -msgid "The user was not found." -msgstr "O usuĆ”rio nĆ£o foi encontrado." - -#: Shell/UsersShell.php:367 -msgid "The user {0} was not deleted. Please try again" -msgstr "O usuĆ”rio {0} nĆ£o foi deletado. Por favor, tente novamente" - -#: Shell/UsersShell.php:369 -msgid "The user {0} was deleted successfully" -msgstr "O usuĆ”rio {0} foi deletado com ĆŖxito" - -#: Template/Email/html/reset_password.ctp:21 -#: Template/Email/html/social_account_validation.ctp:14 -#: Template/Email/html/validation.ctp:21 -#: Template/Email/text/reset_password.ctp:20 -#: Template/Email/text/social_account_validation.ctp:22 -#: Template/Email/text/validation.ctp:20 -msgid "Hi {0}" -msgstr "OlĆ” {0}" - -#: Template/Email/html/reset_password.ctp:24 -msgid "Reset your password here" -msgstr "Redefina sua senha aqui" - -#: Template/Email/html/reset_password.ctp:27 -#: Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 -msgid "" -"If the link is not correctly displayed, please copy the following address in " -"your web browser {0}" -msgstr "" -"Se o link nĆ£o estiver sendo exibido corretamente, por favor, copie o " -"seguinte endereƧo em seu navegador {0}" - -#: Template/Email/html/reset_password.ctp:34 -#: Template/Email/html/social_account_validation.ctp:39 -#: Template/Email/html/validation.ctp:34 -#: Template/Email/text/reset_password.ctp:28 -#: Template/Email/text/social_account_validation.ctp:30 -#: Template/Email/text/validation.ctp:28 -msgid "Thank you" -msgstr "Obrigado" - -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" -msgstr "Ative sua autenticaĆ§Ć£o social aqui" - -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" -msgstr "Ative sua conta aqui" - -#: Template/Email/text/reset_password.ctp:22 -#: Template/Email/text/validation.ctp:22 -msgid "Please copy the following address in your web browser {0}" -msgstr "Por favor, copie o endereƧo a seguir em seu navegador {0}" - -#: Template/Email/text/social_account_validation.ctp:24 -msgid "" -"Please copy the following address in your web browser to activate your " -"social login {0}" -msgstr "" -"Por favor, copie o endereƧo a seguir em seu navegador para ativar sua " -"autenticaĆ§Ć£o social {0}" - -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 -msgid "Actions" -msgstr "AƧƵes" - -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:23 -msgid "List Users" -msgstr "Listar usuĆ”rios" - -#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 -msgid "Add User" -msgstr "Adicionar usuĆ”rio" - -#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 -#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 -#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 -msgid "Username" -msgstr "Nome de usuĆ”rio" - -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 -#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 -msgid "Email" -msgstr "Email" - -#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 -msgid "Password" -msgstr "Senha" - -#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 -msgid "First name" -msgstr "Nome" - -#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 -msgid "Last name" -msgstr "Sobrenome" - -#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:49;74 -msgid "Active" -msgstr "Ativo" - -#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 -#: Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:19 -msgid "Submit" -msgstr "Enviar" - -#: Template/Users/change_password.ctp:5 -msgid "Please enter the new password" -msgstr "Por favor, indique a nova senha" - -#: Template/Users/change_password.ctp:10 -msgid "Current password" -msgstr "Senha atual" - -#: Template/Users/change_password.ctp:16 -msgid "New password" -msgstr "Nova senha" - -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 -msgid "Confirm password" -msgstr "Confirmar senha" - -#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 -msgid "Delete" -msgstr "Deletar" - -#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:21 -msgid "Are you sure you want to delete # {0}?" -msgstr "Tem certeza que deseja deletar # {0}?" - -#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 -msgid "Edit User" -msgstr "Editar usuĆ”rio" - -#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 -msgid "Token" -msgstr "Token" - -#: Template/Users/edit.ctp:41 -msgid "Token expires" -msgstr "Token expira" - -#: Template/Users/edit.ctp:44 -msgid "API token" -msgstr "Token da API" - -#: Template/Users/edit.ctp:47 -msgid "Activation date" -msgstr "Data de ativaĆ§Ć£o" - -#: Template/Users/edit.ctp:50 -msgid "TOS date" -msgstr "Data TOS" - -#: Template/Users/edit.ctp:63 -msgid "Reset Google Authenticator Token" -msgstr "Redefir Token do Google Authenticator" - -#: Template/Users/edit.ctp:69 -msgid "Are you sure you want to reset token for user \"{0}\"?" -msgstr "VocĆŖ tem certeza que deseja redefinir o token para o usuĆ”rio ā€œ{0}ā€?" - -#: Template/Users/index.ctp:15 -msgid "New {0}" -msgstr "Novo {0}" - -#: Template/Users/index.ctp:37 -msgid "View" -msgstr "Visualizar" - -#: Template/Users/index.ctp:38 -msgid "Change password" -msgstr "Alterar senha" - -#: Template/Users/index.ctp:39 -msgid "Edit" -msgstr "Editar" - -#: Template/Users/index.ctp:49 -msgid "previous" -msgstr "anterior" - -#: Template/Users/index.ctp:51 -msgid "next" -msgstr "prĆ³ximo" - -#: Template/Users/login.ctp:19 -msgid "Please enter your username and password" -msgstr "Por favor, indique seu nome de usuĆ”rio e senha" - -#: Template/Users/login.ctp:29 -msgid "Remember me" -msgstr "Lembrar" - -#: Template/Users/login.ctp:37 -msgid "Register" -msgstr "Registrar" - -#: Template/Users/login.ctp:43 -msgid "Reset Password" -msgstr "Resetar Senha" - -#: Template/Users/login.ctp:48 -msgid "Login" -msgstr "Autenticar" - -#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 -msgid "{0} {1}" -msgstr "{0} {1}" - -#: Template/Users/profile.ctp:27 -msgid "Change Password" -msgstr "Mudar senha" - -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 -msgid "Social Accounts" -msgstr "Contas sociais" - -#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 -msgid "Avatar" -msgstr "Avatar" - -#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 -msgid "Provider" -msgstr "Provedor" - -#: Template/Users/profile.ctp:44 -msgid "Link" -msgstr "Link" - -#: Template/Users/profile.ctp:51 -msgid "Link to {0}" -msgstr "Link para {0}" - -#: Template/Users/register.ctp:29 -msgid "Accept TOS conditions?" -msgstr "Concordar com Termos de Uso?" - -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" -msgstr "Por favor, indique seu email para redefinir sua senha" - -#: Template/Users/resend_token_validation.ctp:15 -msgid "Resend Validation email" -msgstr "Reenviar email de validaĆ§Ć£o" - -#: Template/Users/resend_token_validation.ctp:17 -msgid "Email or username" -msgstr "Email ou nome de usuĆ”rio" - -#: Template/Users/verify.ctp:13 -msgid "Verification Code" -msgstr "CĆ³digo de verificaĆ§Ć£o" - -#: Template/Users/verify.ctp:15 -msgid "" -" " -"Verify" -msgstr "" -" Verificar" - -#: Template/Users/view.ctp:19 -msgid "Delete User" -msgstr "Deletar usuĆ”rio" - -#: Template/Users/view.ctp:24 -msgid "New User" -msgstr "Novo usuĆ”rio" - -#: Template/Users/view.ctp:31 -msgid "Id" -msgstr "Id" - -#: Template/Users/view.ctp:37 -msgid "First Name" -msgstr "Nome" - -#: Template/Users/view.ctp:39 -msgid "Last Name" -msgstr "Sobrenome" - -#: Template/Users/view.ctp:41 -msgid "Role" -msgstr "Papel" - -#: Template/Users/view.ctp:45 -msgid "Api Token" -msgstr "Api Token" - -#: Template/Users/view.ctp:53 -msgid "Token Expires" -msgstr "ExpiraĆ§Ć£o do token" - -#: Template/Users/view.ctp:55 -msgid "Activation Date" -msgstr "Data de ativaĆ§Ć£o" - -#: Template/Users/view.ctp:57 -msgid "Tos Date" -msgstr "Data TOS" - -#: Template/Users/view.ctp:59;75 -msgid "Created" -msgstr "Criado" - -#: Template/Users/view.ctp:61;76 -msgid "Modified" -msgstr "Modificado" - -#: View/Helper/UserHelper.php:45 -msgid "Sign in with" -msgstr "Logar com" - -#: View/Helper/UserHelper.php:48 -msgid "fa fa-{0}" -msgstr "fa fa-{0}" - -#: View/Helper/UserHelper.php:57 -msgid "btn btn-social btn-{0} " -msgstr "btn btn-social btn-{0} " - -#: View/Helper/UserHelper.php:106 -msgid "Logout" -msgstr "Desconectar" - -#: View/Helper/UserHelper.php:123 -msgid "Welcome, {0}" -msgstr "Bem-vindo(a), {0}" - -#: View/Helper/UserHelper.php:146 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" -msgstr "" -"reCaptcha nĆ£o estĆ” configurado! Por favor, configure Users.reCaptcha.key" - -#: View/Helper/UserHelper.php:205 -#, fuzzy -#| msgid "btn btn-social btn-{0} " -msgid "btn btn-social btn-{0}" -msgstr "btn btn-social btn-{0}" - -#: View/Helper/UserHelper.php:211 -msgid "Connected with {0}" -msgstr "Conectador com {0}" - -#: View/Helper/UserHelper.php:216 -msgid "Connect with {0}" -msgstr "Conectar com {0}" - -#~ msgid "Type {0} is not valid" -#~ msgstr "Tipo {0} nĆ£o Ć© vĆ”lido" - -#~ msgid "Type {0} has no associated callable" -#~ msgstr "Tipo {0} nĆ£o tem chamada associada" - -#~ msgid "SSL is required for ApiKey Authentication" -#~ msgstr "SSL Ć© requerido para autenticaĆ§Ć£o por chave da API." - -#~ msgid "" -#~ "Missing configuration file: \"config/{0}.php\". Using default permissions" -#~ msgstr "" -#~ "Arquivo de configuraĆ§Ć£o ausente: \"config/{0}.php\". Usando permissƵes " -#~ "padrĆ£o" - -#~ msgid "" -#~ "Table alias is empty, please define a table alias, we could not extract a " -#~ "default table from the request" -#~ msgstr "" -#~ "O alias da tabela estĆ” vazio, por favor, defina um alias de tabela, nĆ³s " -#~ "nĆ£o pudemos extrair uma tabela padrĆ£o da requisiĆ§Ć£o" - -#~ msgid "" -#~ "Missing column {0} in table {1} while checking ownership permissions for " -#~ "user {2}" -#~ msgstr "" -#~ "Coluna {0} ausente na tabela {1} ao verificar permissƵes de propriedade " -#~ "do usuĆ”rio {2}" - -#~ msgid "" -#~ "If the link is not correcly displayed, please copy the following address " -#~ "in your web browser {0}" -#~ msgstr "" -#~ "Se o link nĆ£o estiver sendo exibido corretamente, por favor, copie o " -#~ "seguinte endereƧo em seu navegador {0}" - -#~ msgid "List Accounts" -#~ msgstr "Listar contas" - -#~ msgid "Related Accounts" -#~ msgstr "Contas relacionadas" - -#~ msgid "User Id" -#~ msgstr "Id de usuĆ”rio" - -#~ msgid "Reference" -#~ msgstr "ReferĆŖncia" - -#~ msgid "Data" -#~ msgstr "Dados" - -#~ msgid "This field is required" -#~ msgstr "Este campo Ć© obrigatĆ³rio" - -#~ msgid "The old password does not match" -#~ msgstr "A senha antiga nĆ£o confere" - -#~ msgid "SocialAccount already active" -#~ msgstr "Conta social jĆ” ativa" - -#~ msgid "" -#~ "The social account is not active. Please check your email for " -#~ "instructions. {0}" -#~ msgstr "" -#~ "A conta social nĆ£o estĆ” ativa. Por favor verifique seu email para " -#~ "instruƧƵes. {0}" - -#~ msgid "There was an error associating your social network account" -#~ msgstr "Houve um erro associando sua conta social" - -#~ msgid "Invalid token and/or email" -#~ msgstr "Token e/ou email invĆ”lido(s)" - -#~ msgid "The \"tos\" property is not present" -#~ msgstr "A propriedade ā€œtosā€ nĆ£o estĆ” presente" - -#~ msgid "+ {0} secs" -#~ msgstr "+ {0} segundos" - -#~ msgid "Sign in with Facebook" -#~ msgstr "Inscrever-se com Facebook" - -#~ msgid "Sign in with Twitter" -#~ msgstr "Inscrever-se com Twitter" diff --git a/src/Locale/sv/Users.mo b/src/Locale/sv/Users.mo deleted file mode 100644 index 746e0c282db28536596d3914137f6af5c3ee11cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14831 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 G diff --git a/src/Locale/sv/Users.po b/src/Locale/sv/Users.po deleted file mode 100644 index 839edfdc3..000000000 --- a/src/Locale/sv/Users.po +++ /dev/null @@ -1,864 +0,0 @@ -# LANGUAGE translation of CakePHP Application -# Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com) -# -msgid "" -msgstr "" -"Project-Id-Version: Users\n" -"POT-Creation-Date: 2017-10-25 16:18+0200\n" -"PO-Revision-Date: 2017-10-25 16:24+0200\n" -"Last-Translator: Ulrik Sƶdergren \n" -"Language-Team: CakeDC \n" -"Language: sv\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 1.8.12\n" - -#: Auth/SocialAuthenticate.php:456 -msgid "Provider cannot be empty" -msgstr "Leverantƶr kan inte vara tomt" - -#: Controller/SocialAccountsController.php:52 -msgid "Account validated successfully" -msgstr "Kontot har validerats" - -#: Controller/SocialAccountsController.php:54 -msgid "Account could not be validated" -msgstr "Konto kunde inte valideras" - -#: Controller/SocialAccountsController.php:57 -msgid "Invalid token and/or social account" -msgstr "Ogiltig token och/eller social konto" - -#: Controller/SocialAccountsController.php:59;87 -msgid "Social Account already active" -msgstr "Socialt konto redan aktivt" - -#: Controller/SocialAccountsController.php:61 -msgid "Social Account could not be validated" -msgstr "Socialt konto kunde inte valideras" - -#: Controller/SocialAccountsController.php:80 -msgid "Email sent successfully" -msgstr "Epost har skickats." - -#: Controller/SocialAccountsController.php:82 -msgid "Email could not be sent" -msgstr "Epost kunde inte skickas" - -#: Controller/SocialAccountsController.php:85 -msgid "Invalid account" -msgstr "Ogiltigt konto" - -#: Controller/SocialAccountsController.php:89 -msgid "Email could not be resent" -msgstr "E-post kunde inte skickas om" - -#: Controller/Component/RememberMeComponent.php:68 -msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" -msgstr "" -"Ogiltig app salt, mĆ„ste app salt vara Ć„tminstone 256 bitar (32 byte) lĆ„ngt" - -#: Controller/Component/UsersAuthComponent.php:204 -msgid "You can't enable email validation workflow if use_email is false" -msgstr "" -"Du kan inte aktivera epost-validering arbetsflƶde om use_email Ƥr falskt" - -#: Controller/Traits/LinkSocialTrait.php:54 -msgid "Could not associate account, please try again." -msgstr "Kunde inte ansluta konto, fƶrsƶk igen." - -#: Controller/Traits/LinkSocialTrait.php:77 -msgid "Social account was associated." -msgstr "Socialt konto anslƶts." - -#: Controller/Traits/LoginTrait.php:104 -msgid "Issues trying to log in with your social account" -msgstr "Problem vid inloggning med ditt sociala konto" - -#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 -msgid "Please enter your email" -msgstr "LƤgg till din epost" - -#: Controller/Traits/LoginTrait.php:120 -msgid "" -"Your user has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Ditt konto har inte verifierats Ƥnnu. VƤnligen kontrollera din inbox fƶr " -"instruktioner" - -#: Controller/Traits/LoginTrait.php:125 -msgid "" -"Your social account has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Ditt sociala konto har inte validerats Ƥnnu. Kontrollera din inkorg fƶr " -"instruktioner" - -#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 -msgid "Invalid reCaptcha" -msgstr "Ogiltig reCaptcha" - -#: Controller/Traits/LoginTrait.php:191 -msgid "You are already logged in" -msgstr "Du Ƥr redan inloggad." - -#: Controller/Traits/LoginTrait.php:212 -msgid "Please enable Google Authenticator first." -msgstr "VƤnligen aktivera Google Authenticator fƶrst." - -#: Controller/Traits/LoginTrait.php:287 -msgid "Verification code is invalid. Try again" -msgstr "Valideringskoden Ƥr ogiltig. Fƶrsƶk igen" - -#: Controller/Traits/LoginTrait.php:340 -msgid "Username or password is incorrect" -msgstr "AnvƤndarnamn eller lƶsenord Ƥr felaktigt" - -#: Controller/Traits/LoginTrait.php:363 -msgid "You've successfully logged out" -msgstr "Du har loggats ut" - -#: Controller/Traits/PasswordManagementTrait.php:49;82 -#: Controller/Traits/ProfileTrait.php:50 -msgid "User was not found" -msgstr "AnvƤndaren hittades inte" - -#: Controller/Traits/PasswordManagementTrait.php:70;78;86 -msgid "Password could not be changed" -msgstr "Lƶsenordet kunde inte Ƥndras" - -#: Controller/Traits/PasswordManagementTrait.php:74 -msgid "Password has been changed successfully" -msgstr "Lƶsenordsbytet lyckades!" - -#: Controller/Traits/PasswordManagementTrait.php:84 -msgid "{0}" -msgstr "{0}" - -#: Controller/Traits/PasswordManagementTrait.php:127 -msgid "Please check your email to continue with password reset process" -msgstr "Kontrollera din epost fƶr att fortsƤtta lƶsenordsĆ„terstƤllningen" - -#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 -msgid "The password token could not be generated. Please try again" -msgstr "Lƶsenordstoken kunde inte skapas. Var god fƶrsƶk igen" - -#: Controller/Traits/PasswordManagementTrait.php:136 -#: Controller/Traits/UserValidationTrait.php:107 -msgid "User {0} was not found" -msgstr "AnvƤndaren {0} hittades inte" - -#: Controller/Traits/PasswordManagementTrait.php:138 -msgid "The user is not active" -msgstr "AnvƤndaren Ƥr inte aktiverad" - -#: Controller/Traits/PasswordManagementTrait.php:140 -#: Controller/Traits/UserValidationTrait.php:102;111 -msgid "Token could not be reset" -msgstr "Token kunde inte Ć„terstƤllas" - -#: Controller/Traits/PasswordManagementTrait.php:164 -msgid "Google Authenticator token was successfully reset" -msgstr "Google Authenticator token har Ć„terstƤllts" - -#: Controller/Traits/ProfileTrait.php:54 -msgid "Not authorized, please login first" -msgstr "Inte auktoriserad, vƤnligen logga in fƶrst" - -#: Controller/Traits/RegisterTrait.php:43 -msgid "You must log out to register a new user account" -msgstr "Du mĆ„ste logga ut fƶr att registrera ett nytt anvƤndarkonto" - -#: Controller/Traits/RegisterTrait.php:89 -msgid "The user could not be saved" -msgstr "AnvƤndaren kunde inte sparas" - -#: Controller/Traits/RegisterTrait.php:123 -msgid "You have registered successfully, please log in" -msgstr "Din registrering Ƥr klar, vƤnligen logga in" - -#: Controller/Traits/RegisterTrait.php:125 -msgid "Please validate your account before log in" -msgstr "VƤnligen validera ditt konto innan inloggning" - -#: Controller/Traits/SimpleCrudTrait.php:77;107 -msgid "The {0} has been saved" -msgstr "{0} har sparats" - -#: Controller/Traits/SimpleCrudTrait.php:81;111 -msgid "The {0} could not be saved" -msgstr "{0} kunde inte sparas" - -#: Controller/Traits/SimpleCrudTrait.php:131 -msgid "The {0} has been deleted" -msgstr "{0} har tagits bort" - -#: Controller/Traits/SimpleCrudTrait.php:133 -msgid "The {0} could not be deleted" -msgstr "{0} kunde inte tas bort" - -#: Controller/Traits/SocialTrait.php:40 -msgid "The reCaptcha could not be validated" -msgstr "reCAPTCHA angavs inte korrekt" - -#: Controller/Traits/UserValidationTrait.php:43 -msgid "User account validated successfully" -msgstr "AnvƤndarkontot har validerats" - -#: Controller/Traits/UserValidationTrait.php:45 -msgid "User account could not be validated" -msgstr "AnvƤndarkontot kunde inte valideras" - -#: Controller/Traits/UserValidationTrait.php:48 -msgid "User already active" -msgstr "AnvƤndaren redan aktiv" - -#: Controller/Traits/UserValidationTrait.php:54 -msgid "Reset password token was validated successfully" -msgstr "ƅterstƤllning av lƶsenord lyckades" - -#: Controller/Traits/UserValidationTrait.php:62 -msgid "Reset password token could not be validated" -msgstr "Token fƶr att Ć„terstƤlla lƶsenord kunde inte valideras" - -#: Controller/Traits/UserValidationTrait.php:66 -msgid "Invalid validation type" -msgstr "Ogiltig valideringsmetod" - -#: Controller/Traits/UserValidationTrait.php:69 -msgid "Invalid token or user account already validated" -msgstr "Ogiltig token eller sĆ„ har anvƤndaren konto redan validerats" - -#: Controller/Traits/UserValidationTrait.php:71 -msgid "Token already expired" -msgstr "Token redan lƶpt ut" - -#: Controller/Traits/UserValidationTrait.php:97 -msgid "Token has been reset successfully. Please check your email." -msgstr "Token har Ć„terstƤllts. Kontrollera din e-post." - -#: Controller/Traits/UserValidationTrait.php:109 -msgid "User {0} is already active" -msgstr "AnvƤndaren {0} Ƥr redan aktiv" - -#: Mailer/UsersMailer.php:34 -msgid "Your account validation link" -msgstr "Din lƤnk fƶr att validera kontot" - -#: Mailer/UsersMailer.php:52 -msgid "{0}Your reset password link" -msgstr "{0} Din lƤnk fƶr att Ć„terstƤlla lƶsenord" - -#: Mailer/UsersMailer.php:75 -msgid "{0}Your social account validation link" -msgstr "{0} Din sociala konto svalideringslƤnk" - -#: Model/Behavior/AuthFinderBehavior.php:49 -msgid "Missing 'username' in options data" -msgstr "Saknas 'username' i alternativa uppgifter" - -#: Model/Behavior/LinkSocialBehavior.php:53 -msgid "Social account already associated to another user" -msgstr "Socialt konto Ƥr redan kopplat till en annan anvƤndare." - -#: Model/Behavior/PasswordBehavior.php:45 -msgid "Reference cannot be null" -msgstr "Referens fĆ„r inte vara null" - -#: Model/Behavior/PasswordBehavior.php:50 -msgid "Token expiration cannot be empty" -msgstr "Giltighet fƶr token kan inte vara tom" - -#: Model/Behavior/PasswordBehavior.php:56;117 -msgid "User not found" -msgstr "AnvƤndaren hittades inte" - -#: Model/Behavior/PasswordBehavior.php:60 -#: Model/Behavior/RegisterBehavior.php:112;205 -msgid "User account already validated" -msgstr "Kontot Ƥr redan aktiverat!" - -#: Model/Behavior/PasswordBehavior.php:67 -msgid "User not active" -msgstr "AnvƤndaren ej aktiv" - -#: Model/Behavior/PasswordBehavior.php:122 -msgid "The current password does not match" -msgstr "Den nuvarande lƶsenord matchar inte" - -#: Model/Behavior/PasswordBehavior.php:125 -msgid "You cannot use the current password as the new one" -msgstr "Du kan inte anvƤnda det aktuella lƶsenordet som det nya" - -#: Model/Behavior/RegisterBehavior.php:90 -msgid "User not found for the given token and email." -msgstr "Hittade ingen anvƤndare som matchar angivet token eller epost" - -#: Model/Behavior/RegisterBehavior.php:93 -msgid "Token has already expired user with no token" -msgstr "Token har redan gĆ„tt ut eller anvƤndare utan token" - -#: Model/Behavior/SocialAccountBehavior.php:103;130 -msgid "Account already validated" -msgstr "Kontot Ƥr redan aktiverat!" - -#: Model/Behavior/SocialAccountBehavior.php:106;133 -msgid "Account not found for the given token and email." -msgstr "Kontot hittades inte fƶr givet token och e-post." - -#: Model/Behavior/SocialBehavior.php:82 -msgid "Unable to login user with reference {0}" -msgstr "Det gĆ„r inte att logga in anvƤndaren med refrens {0}" - -#: Model/Behavior/SocialBehavior.php:121 -msgid "Email not present" -msgstr "Epost saknas" - -#: Model/Table/UsersTable.php:81 -msgid "Your password does not match your confirm password. Please try again" -msgstr "Dina lƶsenord matchar inte. VƤnligen fƶrsƶk igen." - -#: Model/Table/UsersTable.php:173 -msgid "Username already exists" -msgstr "AnvƤndarnamnet Ƥr upptaget" - -#: Model/Table/UsersTable.php:179 -msgid "Email already exists" -msgstr "E-postadressen finns redan" - -#: Shell/UsersShell.php:58 -msgid "Utilities for CakeDC Users Plugin" -msgstr "Verktyg fƶr CakeDC User Plugin" - -#: Shell/UsersShell.php:60 -msgid "Activate an specific user" -msgstr "Aktivera en specifik anvƤndare" - -#: Shell/UsersShell.php:63 -msgid "Add a new superadmin user for testing purposes" -msgstr "LƤgga till en ny superadmin anvƤndare fƶr testƤndamĆ„l" - -#: Shell/UsersShell.php:66 -msgid "Add a new user" -msgstr "Ny anvƤndare" - -#: Shell/UsersShell.php:69 -msgid "Change the role for an specific user" -msgstr "Ƅndra rollen fƶr en specifik anvƤndare" - -#: Shell/UsersShell.php:72 -msgid "Deactivate an specific user" -msgstr "Inaktivare en specifik anvƤndare" - -#: Shell/UsersShell.php:75 -msgid "Delete an specific user" -msgstr "Ta bort en specifik anvƤndare" - -#: Shell/UsersShell.php:78 -msgid "Reset the password via email" -msgstr "ƅterstƤll lƶsenord via e-post" - -#: Shell/UsersShell.php:81 -msgid "Reset the password for all users" -msgstr "ƅterstƤll lƶsenord fƶr alla anvƤndare" - -#: Shell/UsersShell.php:84 -msgid "Reset the password for an specific user" -msgstr "ƅterstƤll lƶsenordet fƶr en specifik anvƤndare" - -#: Shell/UsersShell.php:133;159 -msgid "Please enter a password." -msgstr "Ange ett lƶsenord." - -#: Shell/UsersShell.php:137 -msgid "Password changed for all users" -msgstr "Lƶsenordet Ƥndrat fƶr alla anvƤndare" - -#: Shell/UsersShell.php:138;166 -msgid "New password: {0}" -msgstr "Nytt lƶsenord: {0}" - -#: Shell/UsersShell.php:156;184;262;359 -msgid "Please enter a username." -msgstr "Ange ett anvƤndarnamn" - -#: Shell/UsersShell.php:165 -msgid "Password changed for user: {0}" -msgstr "Lƶsenordet Ƥndrat fƶr anvƤndare: {0}" - -#: Shell/UsersShell.php:187 -msgid "Please enter a role." -msgstr "Ange en roll." - -#: Shell/UsersShell.php:193 -msgid "Role changed for user: {0}" -msgstr "Rollen har Ƥndrats fƶr anvƤndare: {0}" - -#: Shell/UsersShell.php:194 -msgid "New role: {0}" -msgstr "Ny roll: {0}" - -#: Shell/UsersShell.php:209 -msgid "User was activated: {0}" -msgstr "AnvƤndaren aktiverades: {0}" - -#: Shell/UsersShell.php:224 -msgid "User was de-activated: {0}" -msgstr "AnvƤndaren avaktiverad: {0}" - -#: Shell/UsersShell.php:236 -msgid "Please enter a username or email." -msgstr "Skriv anvƤndarnamn eller epost" - -#: Shell/UsersShell.php:244 -msgid "" -"Please ask the user to check the email to continue with password reset " -"process" -msgstr "" -"Be anvƤndaren kontrollera sin epost fƶr att fortsƤtta " -"lƶsenordsĆ„terstƤllningen" - -#: Shell/UsersShell.php:308 -msgid "Superuser added:" -msgstr "SuperanvƤndare tillagd:" - -#: Shell/UsersShell.php:310 -msgid "User added:" -msgstr "AnvƤndare tillagd:" - -#: Shell/UsersShell.php:312 -msgid "Id: {0}" -msgstr "Id: {0}" - -#: Shell/UsersShell.php:313 -msgid "Username: {0}" -msgstr "AnvƤndarnamn: {0}" - -#: Shell/UsersShell.php:314 -msgid "Email: {0}" -msgstr "Epost: {0}" - -#: Shell/UsersShell.php:315 -msgid "Role: {0}" -msgstr "Roll: {0}" - -#: Shell/UsersShell.php:316 -msgid "Password: {0}" -msgstr "Lƶsenord: {0}" - -#: Shell/UsersShell.php:318 -msgid "User could not be added:" -msgstr "AnvƤndare kunde inte lƤggas till:" - -#: Shell/UsersShell.php:321 -msgid "Field: {0} Error: {1}" -msgstr "FƤlt: {0} fel: {1}" - -#: Shell/UsersShell.php:337 -msgid "The user was not found." -msgstr "AnvƤndaren hittades inte." - -#: Shell/UsersShell.php:367 -msgid "The user {0} was not deleted. Please try again" -msgstr "AnvƤndaren {0} raderades ej. Var god fƶrsƶk igen" - -#: Shell/UsersShell.php:369 -msgid "The user {0} was deleted successfully" -msgstr "AnvƤndaren {0} har tagits bort" - -#: Template/Email/html/reset_password.ctp:21 -#: Template/Email/html/social_account_validation.ctp:14 -#: Template/Email/html/validation.ctp:21 -#: Template/Email/text/reset_password.ctp:20 -#: Template/Email/text/social_account_validation.ctp:22 -#: Template/Email/text/validation.ctp:20 -msgid "Hi {0}" -msgstr "Hej {0}" - -#: Template/Email/html/reset_password.ctp:24 -msgid "Reset your password here" -msgstr "ƅterstƤll ditt lƶsenord hƤr" - -#: Template/Email/html/reset_password.ctp:27 -#: Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 -msgid "" -"If the link is not correctly displayed, please copy the following address in " -"your web browser {0}" -msgstr "" -"Om lƤnken inte visas korrekt, vƤnligen kopiera fƶljande adress till din " -"webblƤsare {0}" - -#: Template/Email/html/reset_password.ctp:34 -#: Template/Email/html/social_account_validation.ctp:39 -#: Template/Email/html/validation.ctp:34 -#: Template/Email/text/reset_password.ctp:28 -#: Template/Email/text/social_account_validation.ctp:30 -#: Template/Email/text/validation.ctp:28 -msgid "Thank you" -msgstr "Tack" - -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" -msgstr "Aktivera ditt sociala konto hƤr" - -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" -msgstr "Aktivera ditt konto hƤr" - -#: Template/Email/text/reset_password.ctp:22 -#: Template/Email/text/validation.ctp:22 -msgid "Please copy the following address in your web browser {0}" -msgstr "Kopiera fƶljande adress till webblƤsaren {0}" - -#: Template/Email/text/social_account_validation.ctp:24 -msgid "" -"Please copy the following address in your web browser to activate your " -"social login {0}" -msgstr "" -"Kopiera fƶljande adress till din webblƤsare fƶr att aktivera din sociala " -"inloggning {0}" - -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 -msgid "Actions" -msgstr "Resurser" - -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:23 -msgid "List Users" -msgstr "Lista anvƤndare" - -#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 -msgid "Add User" -msgstr "Ny anvƤndare" - -#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 -#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 -#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 -msgid "Username" -msgstr "AnvƤndarnamn" - -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 -#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 -msgid "Email" -msgstr "Epost" - -#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 -msgid "Password" -msgstr "Lƶsenord" - -#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 -msgid "First name" -msgstr "Fƶrnamn" - -#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 -msgid "Last name" -msgstr "Efternamn" - -#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:49;74 -msgid "Active" -msgstr "Aktivt" - -#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 -#: Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:19 -msgid "Submit" -msgstr "Skicka" - -#: Template/Users/change_password.ctp:5 -msgid "Please enter the new password" -msgstr "Ange ditt nya lƶsenord" - -#: Template/Users/change_password.ctp:10 -msgid "Current password" -msgstr "Nuvarande lƶsenord" - -#: Template/Users/change_password.ctp:16 -msgid "New password" -msgstr "Nytt lƶsenord" - -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 -msgid "Confirm password" -msgstr "BekrƤfta lƶsenord" - -#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 -msgid "Delete" -msgstr "Radera" - -#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:21 -msgid "Are you sure you want to delete # {0}?" -msgstr "Ƅr du sƤker pĆ„ att du vill radera{0}" - -#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 -msgid "Edit User" -msgstr "Redigera anvƤndare" - -#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 -msgid "Token" -msgstr "Token" - -#: Template/Users/edit.ctp:41 -msgid "Token expires" -msgstr "Token fƶrfaller" - -#: Template/Users/edit.ctp:44 -msgid "API token" -msgstr "API-token" - -#: Template/Users/edit.ctp:47 -msgid "Activation date" -msgstr "Aktiveringsdatum" - -#: Template/Users/edit.ctp:50 -msgid "TOS date" -msgstr "TOS datum" - -#: Template/Users/edit.ctp:63 -msgid "Reset Google Authenticator Token" -msgstr "ƅterstƤll Google Authenticator Token" - -#: Template/Users/edit.ctp:69 -msgid "Are you sure you want to reset token for user \"{0}\"?" -msgstr "Ƅr du sƤker du vill Ć„terstƤlla token fƶr anvƤndare \"{0}\"?" - -#: Template/Users/index.ctp:15 -msgid "New {0}" -msgstr "Nytt {0}" - -#: Template/Users/index.ctp:37 -msgid "View" -msgstr "Visa" - -#: Template/Users/index.ctp:38 -msgid "Change password" -msgstr "Byt lƶsenord" - -#: Template/Users/index.ctp:39 -msgid "Edit" -msgstr "Ƅndra" - -#: Template/Users/index.ctp:49 -msgid "previous" -msgstr "fƶregĆ„ende" - -#: Template/Users/index.ctp:51 -msgid "next" -msgstr "nƤsta" - -#: Template/Users/login.ctp:19 -msgid "Please enter your username and password" -msgstr "Ange ditt anvƤndarnamn och lƶsenord" - -#: Template/Users/login.ctp:29 -msgid "Remember me" -msgstr "Kom ihĆ„g mig" - -#: Template/Users/login.ctp:37 -msgid "Register" -msgstr "Registrera" - -#: Template/Users/login.ctp:43 -msgid "Reset Password" -msgstr "ƅterstƤll Lƶsenord" - -#: Template/Users/login.ctp:48 -msgid "Login" -msgstr "Logga in" - -#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 -msgid "{0} {1}" -msgstr "{0} {1}" - -#: Template/Users/profile.ctp:27 -msgid "Change Password" -msgstr "Ƅndra Lƶsenord" - -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 -msgid "Social Accounts" -msgstr "Sociala konton" - -#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 -msgid "Avatar" -msgstr "Profilbild" - -#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 -msgid "Provider" -msgstr "Utfƶrare" - -#: Template/Users/profile.ctp:44 -msgid "Link" -msgstr "LƤnk" - -#: Template/Users/profile.ctp:51 -msgid "Link to {0}" -msgstr "LƤnk till {0}" - -#: Template/Users/register.ctp:29 -msgid "Accept TOS conditions?" -msgstr "Jag accepterar villkoren" - -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" -msgstr "Ange din e-postadress fƶr att Ć„terstƤlla ditt lƶsenord" - -#: Template/Users/resend_token_validation.ctp:15 -msgid "Resend Validation email" -msgstr "Skicka nytt bekrƤftelsemejl" - -#: Template/Users/resend_token_validation.ctp:17 -msgid "Email or username" -msgstr "E-post/AnvƤndarnamn" - -#: Template/Users/verify.ctp:13 -msgid "Verification Code" -msgstr "Verifieringskod" - -#: Template/Users/verify.ctp:15 -msgid "" -" " -"Verify" -msgstr "" -" " -"Verifiera" - -#: Template/Users/view.ctp:19 -msgid "Delete User" -msgstr "Ta bort anvƤndare" - -#: Template/Users/view.ctp:24 -msgid "New User" -msgstr "Ny anvƤndare" - -#: Template/Users/view.ctp:31 -msgid "Id" -msgstr "Id" - -#: Template/Users/view.ctp:37 -msgid "First Name" -msgstr "Fƶrnamn" - -#: Template/Users/view.ctp:39 -msgid "Last Name" -msgstr "Efternamn" - -#: Template/Users/view.ctp:41 -msgid "Role" -msgstr "Roll" - -#: Template/Users/view.ctp:45 -msgid "Api Token" -msgstr "Api-token" - -#: Template/Users/view.ctp:53 -msgid "Token Expires" -msgstr "Token fƶrfaller" - -#: Template/Users/view.ctp:55 -msgid "Activation Date" -msgstr "Aktiveringsdatum" - -#: Template/Users/view.ctp:57 -msgid "Tos Date" -msgstr "Tos datum" - -#: Template/Users/view.ctp:59;75 -msgid "Created" -msgstr "Skapad" - -#: Template/Users/view.ctp:61;76 -msgid "Modified" -msgstr "Ƅndrad" - -#: View/Helper/UserHelper.php:45 -msgid "Sign in with" -msgstr "Logga in med" - -#: View/Helper/UserHelper.php:48 -msgid "fa fa-{0}" -msgstr "fa fa-{0}" - -#: View/Helper/UserHelper.php:57 -msgid "btn btn-social btn-{0} " -msgstr "btn btn-social btn-{0} " - -#: View/Helper/UserHelper.php:106 -msgid "Logout" -msgstr "Logga ut" - -#: View/Helper/UserHelper.php:123 -msgid "Welcome, {0}" -msgstr "VƤlkommen, {0}" - -#: View/Helper/UserHelper.php:146 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" -msgstr "reCaptcha Ƥr inte konfigurerad! Konfigurera Users.reCaptcha.key" - -#: View/Helper/UserHelper.php:205 -msgid "btn btn-social btn-{0}" -msgstr "btn btn-social btn-{0} " - -#: View/Helper/UserHelper.php:211 -msgid "Connected with {0}" -msgstr "Ansluten med {0}" - -#: View/Helper/UserHelper.php:216 -msgid "Connect with {0}" -msgstr "Anslut med {0}" - -#~ msgid "Type {0} is not valid" -#~ msgstr "Typ {0} Ƥr inte giltig" - -#~ msgid "Type {0} has no associated callable" -#~ msgstr "Typ {0} har inget tillhƶrande anrop" - -#~ msgid "SSL is required for ApiKey Authentication" -#~ msgstr "SSL krƤvs fƶr ApiKey-autentisering" - -#~ msgid "" -#~ "Missing configuration file: \"config/{0}.php\". Using default permissions" -#~ msgstr "" -#~ "Saknad konfigurationsfil: \"config / {0} .php\". AnvƤnder " -#~ "standardbehƶrigheter" - -#~ msgid "" -#~ "Table alias is empty, please define a table alias, we could not extract a " -#~ "default table from the request" -#~ msgstr "" -#~ "Tabellalias Ƥr tomt, var vƤnlig ange ett tabellalias, vi kunde inte " -#~ "extrahera nĆ„gon standardtabell" - -#~ msgid "" -#~ "Missing column {0} in table {1} while checking ownership permissions for " -#~ "user {2}" -#~ msgstr "" -#~ "Saknar kolumn {0} i tabell {1} vid kontroll av Ƥgarbehƶrigheter fƶr " -#~ "anvƤndare {2}" - -#~ msgid "List Accounts" -#~ msgstr "Lista konton" - -#~ msgid "Related Accounts" -#~ msgstr "Relaterade konton" - -#~ msgid "User Id" -#~ msgstr "AnvƤndar-ID" - -#~ msgid "Reference" -#~ msgstr "Referens" - -#~ msgid "Data" -#~ msgstr "Data" - -#~ msgid "This field is required" -#~ msgstr "Detta fƤlt Ƥr obligatoriskt" diff --git a/src/Locale/tr_TR/Users.mo b/src/Locale/tr_TR/Users.mo deleted file mode 100644 index c65ebec0d2712a5e0117fa2b0d3ae8d036658bdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15267 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 t5bsklw -# -msgid "" -msgstr "" -"Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2017-10-14 23:45+0000\n" -"PO-Revision-Date: 2018-01-22 22:21+0300\n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 2.0.6\n" -"Last-Translator: \n" -"Language: tr_TR\n" - -#: Auth/SocialAuthenticate.php:456 -msgid "Provider cannot be empty" -msgstr "Sağlayıcı boş olamaz" - -#: Controller/SocialAccountsController.php:52 -msgid "Account validated successfully" -msgstr "Hesap başarıyla doğrulandı" - -#: Controller/SocialAccountsController.php:54 -msgid "Account could not be validated" -msgstr "Hesap doğrulanamadı" - -#: Controller/SocialAccountsController.php:57 -msgid "Invalid token and/or social account" -msgstr "GeƧersiz jeton ve/veya sosyal hesap" - -#: Controller/SocialAccountsController.php:59;87 -msgid "Social Account already active" -msgstr "Sosyal Hesap zaten aktif" - -#: Controller/SocialAccountsController.php:61 -msgid "Social Account could not be validated" -msgstr "Sosyal Hesap doğrulanamadı" - -#: Controller/SocialAccountsController.php:80 -msgid "Email sent successfully" -msgstr "E-posta başarıyla gƶnderildi" - -#: Controller/SocialAccountsController.php:82 -msgid "Email could not be sent" -msgstr "E-posta gƶnderilemedi" - -#: Controller/SocialAccountsController.php:85 -msgid "Invalid account" -msgstr "GeƧersiz hesap" - -#: Controller/SocialAccountsController.php:89 -msgid "Email could not be resent" -msgstr "E-posta tekrar gƶnderilemedi" - -#: Controller/Component/RememberMeComponent.php:68 -msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" -msgstr "" -"GeƧersiz tuz kodu, tuz kodu en az 256 bit (32 bayt) ā€œlongā€ uzunluğunda olmalı" - -#: Controller/Component/UsersAuthComponent.php:204 -msgid "You can't enable email validation workflow if use_email is false" -msgstr "" -"Eğer use_email yanlışsa, e-posta doğrulama iş akışını etkinleştiremezsin" - -#: Controller/Traits/LinkSocialTrait.php:54 -msgid "Could not associate account, please try again." -msgstr "Hesap eşleştirilemedi, lĆ¼tfen tekrar deneyin." - -#: Controller/Traits/LinkSocialTrait.php:77 -msgid "Social account was associated." -msgstr "Sosyal hesap zaten eşleştirilmişti." - -#: Controller/Traits/LoginTrait.php:104 -msgid "Issues trying to log in with your social account" -msgstr "Sosyal hesabınız ile giriş yaparken Ƨıkan sorunlar" - -#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 -msgid "Please enter your email" -msgstr "LĆ¼tfen e-posta hesabınızı girin" - -#: Controller/Traits/LoginTrait.php:120 -msgid "" -"Your user has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Kullanıcınız henĆ¼z doğrulanmadı. LĆ¼tfen talimatlar iƧin gelen kutunuzu " -"kontrol edin" - -#: Controller/Traits/LoginTrait.php:125 -msgid "" -"Your social account has not been validated yet. Please check your inbox for " -"instructions" -msgstr "" -"Sosyal hesabınız henĆ¼z doğrulanmadı. LĆ¼tfen talimatlar iƧin gelen kutunuzu " -"kontrol edin" - -#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 -msgid "Invalid reCaptcha" -msgstr "GeƧersiz reCaptcha" - -#: Controller/Traits/LoginTrait.php:191 -msgid "You are already logged in" -msgstr "Zaten giriş yapmış durumdasınız" - -#: Controller/Traits/LoginTrait.php:212 -msgid "Please enable Google Authenticator first." -msgstr "LĆ¼tfen ƶnce Google Authenticator ā€˜Ä± aktif hale getirin." - -#: Controller/Traits/LoginTrait.php:287 -msgid "Verification code is invalid. Try again" -msgstr "Doğrulama kodu yanlış. Tekrar deneyin" - -#: Controller/Traits/LoginTrait.php:340 -msgid "Username or password is incorrect" -msgstr "Kullanıcı adınız veya şifreniz yanlış" - -#: Controller/Traits/LoginTrait.php:363 -msgid "You've successfully logged out" -msgstr "Başarıyla Ƨıkış yaptınız" - -#: Controller/Traits/PasswordManagementTrait.php:49;82 -#: Controller/Traits/ProfileTrait.php:50 -msgid "User was not found" -msgstr "Kullanıcı bulunamadı" - -#: Controller/Traits/PasswordManagementTrait.php:70;78;86 -msgid "Password could not be changed" -msgstr "Şifre değiştirilemedi" - -#: Controller/Traits/PasswordManagementTrait.php:74 -msgid "Password has been changed successfully" -msgstr "Şifre başarıyla değiştirildi" - -#: Controller/Traits/PasswordManagementTrait.php:84 -msgid "{0}" -msgstr "{0}" - -#: Controller/Traits/PasswordManagementTrait.php:127 -msgid "Please check your email to continue with password reset process" -msgstr "" -"Şifre sıfırlama işleminize devam edebilmek iƧin lĆ¼tfen e-postanızı kontrol " -"edin" - -#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 -msgid "The password token could not be generated. Please try again" -msgstr "Şifre jetonu oluşturulamadı. LĆ¼tfen tekrar deneyin" - -#: Controller/Traits/PasswordManagementTrait.php:136 -#: Controller/Traits/UserValidationTrait.php:107 -msgid "User {0} was not found" -msgstr "Kullancı {0} bulunamadı" - -#: Controller/Traits/PasswordManagementTrait.php:138 -msgid "The user is not active" -msgstr "Kullanıcı aktif değil" - -#: Controller/Traits/PasswordManagementTrait.php:140 -#: Controller/Traits/UserValidationTrait.php:102;111 -msgid "Token could not be reset" -msgstr "Jeton sıfırlanamadı" - -#: Controller/Traits/PasswordManagementTrait.php:164 -msgid "Google Authenticator token was successfully reset" -msgstr "Google Authenticator jetonu başarıyla sıfırlandı" - -#: Controller/Traits/ProfileTrait.php:54 -msgid "Not authorized, please login first" -msgstr "Yetkili değil, lĆ¼tfen ilk ƶnce giriş yapın" - -#: Controller/Traits/RegisterTrait.php:43 -msgid "You must log out to register a new user account" -msgstr "Yeni bir hesap oluşturmak oluşturmak iƧin ƶnce Ƨıkış yapmanız gerekli" - -#: Controller/Traits/RegisterTrait.php:89 -msgid "The user could not be saved" -msgstr "Kullanıcı kaydedilemedi" - -#: Controller/Traits/RegisterTrait.php:123 -msgid "You have registered successfully, please log in" -msgstr "Başarıyla kayıt oldunuz, lĆ¼tfen giriş yapın" - -#: Controller/Traits/RegisterTrait.php:125 -msgid "Please validate your account before log in" -msgstr "LĆ¼tfen giriş yapmadan ƶnce hesabınızı doğrulayın" - -#: Controller/Traits/SimpleCrudTrait.php:77;107 -msgid "The {0} has been saved" -msgstr "{0} kaydedildi" - -#: Controller/Traits/SimpleCrudTrait.php:81;111 -msgid "The {0} could not be saved" -msgstr "{0} kaydedilemedi" - -#: Controller/Traits/SimpleCrudTrait.php:131 -msgid "The {0} has been deleted" -msgstr "{0} silindi" - -#: Controller/Traits/SimpleCrudTrait.php:133 -msgid "The {0} could not be deleted" -msgstr "{0} silinemedi" - -#: Controller/Traits/SocialTrait.php:40 -msgid "The reCaptcha could not be validated" -msgstr "reCaptcha doğrulanamadı" - -#: Controller/Traits/UserValidationTrait.php:43 -msgid "User account validated successfully" -msgstr "Kullanıcı hesabı başarıyla doğrulandı" - -#: Controller/Traits/UserValidationTrait.php:45 -msgid "User account could not be validated" -msgstr "Kullanıcı hesabı doğrulanamadı" - -#: Controller/Traits/UserValidationTrait.php:48 -msgid "User already active" -msgstr "Kullanıcı zaten aktif" - -#: Controller/Traits/UserValidationTrait.php:54 -msgid "Reset password token was validated successfully" -msgstr "Şifre sıfırlama jetonu başarıyla doğrulandı" - -#: Controller/Traits/UserValidationTrait.php:62 -msgid "Reset password token could not be validated" -msgstr "Şifre sıfırlama jetonu doğrulanamadı" - -#: Controller/Traits/UserValidationTrait.php:66 -msgid "Invalid validation type" -msgstr "GeƧersiz doğrulama cinsi" - -#: Controller/Traits/UserValidationTrait.php:69 -msgid "Invalid token or user account already validated" -msgstr "GeƧersiz jeton veya kullanıcı hesabı zaten doğrulandı" - -#: Controller/Traits/UserValidationTrait.php:71 -msgid "Token already expired" -msgstr "Jeton sĆ¼resi zaten doldu" - -#: Controller/Traits/UserValidationTrait.php:97 -msgid "Token has been reset successfully. Please check your email." -msgstr "Jeton başarıyla sıfırlandı. LĆ¼tfen e-postanızı kontrol edin." - -#: Controller/Traits/UserValidationTrait.php:109 -msgid "User {0} is already active" -msgstr "Kullanıcı {0} zaten aktif" - -#: Mailer/UsersMailer.php:34 -msgid "Your account validation link" -msgstr "Hesap doğrulama bağlantısı" - -#: Mailer/UsersMailer.php:52 -msgid "{0}Your reset password link" -msgstr "{0} Şifre sıfırlama bağlantısı" - -#: Mailer/UsersMailer.php:75 -msgid "{0}Your social account validation link" -msgstr "{0} Sosyal hesap doğrulama bağlantısı" - -#: Model/Behavior/AuthFinderBehavior.php:49 -msgid "Missing 'username' in options data" -msgstr "SeƧenekler verilerinde ā€˜kullanıcı adıā€™ eksik" - -#: Model/Behavior/LinkSocialBehavior.php:53 -msgid "Social account already associated to another user" -msgstr "Sosyal hesap zaten başka bir kullanıcıyla eşleşmiş durumda" - -#: Model/Behavior/PasswordBehavior.php:45 -msgid "Reference cannot be null" -msgstr "Referans boş olamaz" - -#: Model/Behavior/PasswordBehavior.php:50 -msgid "Token expiration cannot be empty" -msgstr "Jeton son kullanma tarihi boş olamaz" - -#: Model/Behavior/PasswordBehavior.php:56;117 -msgid "User not found" -msgstr "Kullanıcı bulunamadı" - -#: Model/Behavior/PasswordBehavior.php:60 -#: Model/Behavior/RegisterBehavior.php:112;205 -msgid "User account already validated" -msgstr "Kullanıcı hesabı zaten doğrulandı" - -#: Model/Behavior/PasswordBehavior.php:67 -msgid "User not active" -msgstr "Kullanıcı aktif durumda değil" - -#: Model/Behavior/PasswordBehavior.php:122 -msgid "The current password does not match" -msgstr "GeƧerli şifre uyuşmuyor" - -#: Model/Behavior/PasswordBehavior.php:125 -msgid "You cannot use the current password as the new one" -msgstr "GeƧerli şifrenizi yeni bir şifre olarak kullanamazsınız" - -#: Model/Behavior/RegisterBehavior.php:90 -msgid "User not found for the given token and email." -msgstr "Verilen jeton ve e-posta iƧin kullanıcı bulunamadı." - -#: Model/Behavior/RegisterBehavior.php:93 -msgid "Token has already expired user with no token" -msgstr "Jeton son kullanma tarihi zaten doldu, kullanıcının jetonu yok" - -#: Model/Behavior/SocialAccountBehavior.php:103;130 -msgid "Account already validated" -msgstr "Hesap zaten doğrulandı" - -#: Model/Behavior/SocialAccountBehavior.php:106;133 -msgid "Account not found for the given token and email." -msgstr "Verilen jeton ve e-posta iƧin hesap bulunamadı." - -#: Model/Behavior/SocialBehavior.php:82 -msgid "Unable to login user with reference {0}" -msgstr "Referans {0} ile giriş başarısız" - -#: Model/Behavior/SocialBehavior.php:121 -msgid "Email not present" -msgstr "E-posta yok" - -#: Model/Table/UsersTable.php:81 -msgid "Your password does not match your confirm password. Please try again" -msgstr "Şifreniz onay şifreniz ile uyuşmuyor. LĆ¼tfen tekrar deneyin" - -#: Model/Table/UsersTable.php:173 -msgid "Username already exists" -msgstr "Kullanıcı adı zaten var" - -#: Model/Table/UsersTable.php:179 -msgid "Email already exists" -msgstr "E-posta zaten var" - -#: Shell/UsersShell.php:58 -msgid "Utilities for CakeDC Users Plugin" -msgstr "CakeDC Users eklentisi iƧin araƧlar" - -#: Shell/UsersShell.php:60 -msgid "Activate an specific user" -msgstr "Belirli bir kullanıcıyı aktif hale getir" - -#: Shell/UsersShell.php:63 -msgid "Add a new superadmin user for testing purposes" -msgstr "Deneme iƧin yeni bir sĆ¼peryƶnetici kullanıcısı ekle" - -#: Shell/UsersShell.php:66 -msgid "Add a new user" -msgstr "Yeni bir kullanıcı ekle" - -#: Shell/UsersShell.php:69 -msgid "Change the role for an specific user" -msgstr "Belirli bir kullanıcının rolĆ¼nĆ¼ değiştir" - -#: Shell/UsersShell.php:72 -msgid "Deactivate an specific user" -msgstr "Belirli bir kullanıcıyı devre dışı bırak" - -#: Shell/UsersShell.php:75 -msgid "Delete an specific user" -msgstr "Belirli bir kullanıcıyı sil" - -#: Shell/UsersShell.php:78 -msgid "Reset the password via email" -msgstr "Şifreyi e-posta aracılığıyla sıfırla" - -#: Shell/UsersShell.php:81 -msgid "Reset the password for all users" -msgstr "TĆ¼m kullanıcıların şifrelerini sıfırla" - -#: Shell/UsersShell.php:84 -msgid "Reset the password for an specific user" -msgstr "Belirli bir kullanıcının şifresini sıfırla" - -#: Shell/UsersShell.php:133;159 -msgid "Please enter a password." -msgstr "LĆ¼tfen bir şifre gir." - -#: Shell/UsersShell.php:137 -msgid "Password changed for all users" -msgstr "TĆ¼m kullanıcıların şifreleri değiştirildi" - -#: Shell/UsersShell.php:138;166 -msgid "New password: {0}" -msgstr "Yeni şifre: {0}" - -#: Shell/UsersShell.php:156;184;262;359 -msgid "Please enter a username." -msgstr "LĆ¼tfen bir kullanıcı adı gir." - -#: Shell/UsersShell.php:165 -msgid "Password changed for user: {0}" -msgstr "Kullanıcı iƧin şifre değiştirildi: {0}" - -#: Shell/UsersShell.php:187 -msgid "Please enter a role." -msgstr "LĆ¼tfen bir rol gir." - -#: Shell/UsersShell.php:193 -msgid "Role changed for user: {0}" -msgstr "Kullanıcı rolĆ¼ değiştirildi: {0}" - -#: Shell/UsersShell.php:194 -msgid "New role: {0}" -msgstr "Yeni rol: {0}" - -#: Shell/UsersShell.php:209 -msgid "User was activated: {0}" -msgstr "Kullanıcı aktif hale getirildi: {0}" - -#: Shell/UsersShell.php:224 -msgid "User was de-activated: {0}" -msgstr "Kullanıcı devre dışı bırakıldı: {0}" - -#: Shell/UsersShell.php:236 -msgid "Please enter a username or email." -msgstr "LĆ¼tfen kullanıcı adı veya e-posta girin." - -#: Shell/UsersShell.php:244 -msgid "" -"Please ask the user to check the email to continue with password reset " -"process" -msgstr "" -"Şifre sıfırlama işlemine devam etmek iƧin, lĆ¼tfen kullanıcıya e-posta " -"hesabını kontrol etmesini sƶyleyin" - -#: Shell/UsersShell.php:308 -msgid "Superuser added:" -msgstr "SĆ¼perkullanıcı eklendi:" - -#: Shell/UsersShell.php:310 -msgid "User added:" -msgstr "Kullanıcı eklendi:" - -#: Shell/UsersShell.php:312 -msgid "Id: {0}" -msgstr "Id: {0}" - -#: Shell/UsersShell.php:313 -msgid "Username: {0}" -msgstr "Kullanıcı Adı: {0}" - -#: Shell/UsersShell.php:314 -msgid "Email: {0}" -msgstr "E-posta: {0}" - -#: Shell/UsersShell.php:315 -msgid "Role: {0}" -msgstr "Rol: {0}" - -#: Shell/UsersShell.php:316 -msgid "Password: {0}" -msgstr "Şifre: {0}" - -#: Shell/UsersShell.php:318 -msgid "User could not be added:" -msgstr "Kullanıcı eklenemedi:" - -#: Shell/UsersShell.php:321 -msgid "Field: {0} Error: {1}" -msgstr "Alan: {0} Hata: {1}" - -#: Shell/UsersShell.php:337 -msgid "The user was not found." -msgstr "Kullanıcı bulunamadı." - -#: Shell/UsersShell.php:367 -msgid "The user {0} was not deleted. Please try again" -msgstr "Kullanıcı {0} silinemedi. LĆ¼tfen tekrar deneyin" - -#: Shell/UsersShell.php:369 -msgid "The user {0} was deleted successfully" -msgstr "Kullanıcı {0} başarıyla silindi" - -#: Template/Email/html/reset_password.ctp:21 -#: Template/Email/html/social_account_validation.ctp:14 -#: Template/Email/html/validation.ctp:21 -#: Template/Email/text/reset_password.ctp:20 -#: Template/Email/text/social_account_validation.ctp:22 -#: Template/Email/text/validation.ctp:20 -msgid "Hi {0}" -msgstr "Merhaba {0}" - -#: Template/Email/html/reset_password.ctp:24 -msgid "Reset your password here" -msgstr "Şifrenizi buradan sıfırlayın" - -#: Template/Email/html/reset_password.ctp:27 -#: Template/Email/html/social_account_validation.ctp:32 -#: Template/Email/html/validation.ctp:27 -msgid "" -"If the link is not correctly displayed, please copy the following address in " -"your web browser {0}" -msgstr "" -"Eğer bağlantı dĆ¼zgĆ¼n şekilde gƶzĆ¼kmĆ¼yorsa, lĆ¼tfen adresi internet tarayıcına " -"kopyala {0}" - -#: Template/Email/html/reset_password.ctp:34 -#: Template/Email/html/social_account_validation.ctp:39 -#: Template/Email/html/validation.ctp:34 -#: Template/Email/text/reset_password.ctp:28 -#: Template/Email/text/social_account_validation.ctp:30 -#: Template/Email/text/validation.ctp:28 -msgid "Thank you" -msgstr "TeşekkĆ¼rler" - -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" -msgstr "Sosyal girişi buradan aktif hale getirin" - -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" -msgstr "Hesabınızı buradan aktif hale getirin" - -#: Template/Email/text/reset_password.ctp:22 -#: Template/Email/text/validation.ctp:22 -msgid "Please copy the following address in your web browser {0}" -msgstr "LĆ¼tfen adresi internet tarayıcınıza kopyalayın {0}" - -#: Template/Email/text/social_account_validation.ctp:24 -msgid "" -"Please copy the following address in your web browser to activate your " -"social login {0}" -msgstr "" -"LĆ¼tfen sosyal girişi aktif hale getirmek iƧin adresi internet tarayıcınıza " -"kopyalayın {0}" - -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 -msgid "Actions" -msgstr "Aksiyonlar" - -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 -#: Template/Users/view.ctp:23 -msgid "List Users" -msgstr "Kullanıcıları Listele" - -#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 -msgid "Add User" -msgstr "Kullanıcı Ekle" - -#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 -#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 -#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 -msgid "Username" -msgstr "Kullanıcı Adı" - -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 -#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 -msgid "Email" -msgstr "E-posta" - -#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 -msgid "Password" -msgstr "Şifre" - -#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 -msgid "First name" -msgstr "Ad" - -#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 -msgid "Last name" -msgstr "Soyad" - -#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 -#: Template/Users/view.ctp:49;74 -msgid "Active" -msgstr "Aktif" - -#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 -#: Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:19 -msgid "Submit" -msgstr "Gƶnder" - -#: Template/Users/change_password.ctp:5 -msgid "Please enter the new password" -msgstr "LĆ¼tfen yeni bir şifre gir" - -#: Template/Users/change_password.ctp:10 -msgid "Current password" -msgstr "GeƧerli şifre" - -#: Template/Users/change_password.ctp:16 -msgid "New password" -msgstr "Yeni şifre" - -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 -msgid "Confirm password" -msgstr "Şifre onayla" - -#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 -msgid "Delete" -msgstr "Sil" - -#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:21 -msgid "Are you sure you want to delete # {0}?" -msgstr "Silmek istediğine emin misin # {0}?" - -#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 -msgid "Edit User" -msgstr "Kullanıcıyı dĆ¼zenle" - -#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 -msgid "Token" -msgstr "Jeton" - -#: Template/Users/edit.ctp:41 -msgid "Token expires" -msgstr "Jeton Son Kullanma Tarihi" - -#: Template/Users/edit.ctp:44 -msgid "API token" -msgstr "API jetonu" - -#: Template/Users/edit.ctp:47 -msgid "Activation date" -msgstr "Aktivasyon tarihi" - -#: Template/Users/edit.ctp:50 -msgid "TOS date" -msgstr "TOS tarihi" - -#: Template/Users/edit.ctp:63 -msgid "Reset Google Authenticator Token" -msgstr "Google Authenticator Jetonunu Sıfırla" - -#: Template/Users/edit.ctp:69 -msgid "Are you sure you want to reset token for user \"{0}\"?" -msgstr "Kullanıcı {0} iƧin jetonu sıfırlamak istediğine emin misin?" - -#: Template/Users/index.ctp:15 -msgid "New {0}" -msgstr "Yeni {0}" - -#: Template/Users/index.ctp:37 -msgid "View" -msgstr "GƶrĆ¼nĆ¼m" - -#: Template/Users/index.ctp:38 -msgid "Change password" -msgstr "Şifre değiştir" - -#: Template/Users/index.ctp:39 -msgid "Edit" -msgstr "DĆ¼zenle" - -#: Template/Users/index.ctp:49 -msgid "previous" -msgstr "ƶnceki" - -#: Template/Users/index.ctp:51 -msgid "next" -msgstr "sonraki" - -#: Template/Users/login.ctp:19 -msgid "Please enter your username and password" -msgstr "LĆ¼tfen kullanıcı adını ve şifreni gir" - -#: Template/Users/login.ctp:29 -msgid "Remember me" -msgstr "Beni Hatırla" - -#: Template/Users/login.ctp:37 -msgid "Register" -msgstr "Kayıt Ol" - -#: Template/Users/login.ctp:43 -msgid "Reset Password" -msgstr "Şifre Sıfırla" - -#: Template/Users/login.ctp:48 -msgid "Login" -msgstr "Giriş" - -#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 -msgid "{0} {1}" -msgstr "{0} {1}" - -#: Template/Users/profile.ctp:27 -msgid "Change Password" -msgstr "Şifre Değiştir" - -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 -msgid "Social Accounts" -msgstr "Sosyal Hesaplar" - -#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 -msgid "Avatar" -msgstr "Avatar" - -#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 -msgid "Provider" -msgstr "Sağlayıcı" - -#: Template/Users/profile.ctp:44 -msgid "Link" -msgstr "Bağlantı" - -#: Template/Users/profile.ctp:51 -msgid "Link to {0}" -msgstr "Şuna bağlı {0}" - -#: Template/Users/register.ctp:29 -msgid "Accept TOS conditions?" -msgstr "TOS koşullarını kabul ediyor musun?" - -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" -msgstr "Şifreni sıfırlamak iƧin lĆ¼tfen e-postanı gir" - -#: Template/Users/resend_token_validation.ctp:15 -msgid "Resend Validation email" -msgstr "Doğrulama e-postasını yeniden gƶnder" - -#: Template/Users/resend_token_validation.ctp:17 -msgid "Email or username" -msgstr "E-posta veta kullanıcı adı" - -#: Template/Users/verify.ctp:13 -msgid "Verification Code" -msgstr "Doğrulama Kodu" - -#: Template/Users/verify.ctp:15 -msgid "" -" " -"Verify" -msgstr "" -" Verify" - -#: Template/Users/view.ctp:19 -msgid "Delete User" -msgstr "Kullanıcıyı Sil" - -#: Template/Users/view.ctp:24 -msgid "New User" -msgstr "Yeni Kullanıcı" - -#: Template/Users/view.ctp:31 -msgid "Id" -msgstr "Id" - -#: Template/Users/view.ctp:37 -msgid "First Name" -msgstr "Ad" - -#: Template/Users/view.ctp:39 -msgid "Last Name" -msgstr "Soyad" - -#: Template/Users/view.ctp:41 -msgid "Role" -msgstr "Rol" - -#: Template/Users/view.ctp:45 -msgid "Api Token" -msgstr "Api Jeton" - -#: Template/Users/view.ctp:53 -msgid "Token Expires" -msgstr "Jeton Bitiş Tarihi" - -#: Template/Users/view.ctp:55 -msgid "Activation Date" -msgstr "Aktivasyon Tarihi" - -#: Template/Users/view.ctp:57 -msgid "Tos Date" -msgstr "Tos Tarihi" - -#: Template/Users/view.ctp:59;75 -msgid "Created" -msgstr "Oluşturulmuş" - -#: Template/Users/view.ctp:61;76 -msgid "Modified" -msgstr "Değiştirilmiş" - -#: View/Helper/UserHelper.php:45 -msgid "Sign in with" -msgstr "Şununla giriş yapın" - -#: View/Helper/UserHelper.php:48 -msgid "fa fa-{0}" -msgstr "fa fa-{0}" - -#: View/Helper/UserHelper.php:57 -msgid "btn btn-social btn-{0} " -msgstr "btn btn-social btn-{0} " - -#: View/Helper/UserHelper.php:106 -msgid "Logout" -msgstr "Ƈıkış" - -#: View/Helper/UserHelper.php:123 -msgid "Welcome, {0}" -msgstr "Hoşgeldiniz, {0}" - -#: View/Helper/UserHelper.php:146 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" -msgstr "" -"reCaptcha konfigĆ¼re edilmedi! LĆ¼tfen konfigĆ¼re edin Users.reCaptcha.key" - -#: View/Helper/UserHelper.php:205 -msgid "btn btn-social btn-{0}" -msgstr "btn btn-social btn-{0}" - -#: View/Helper/UserHelper.php:211 -msgid "Connected with {0}" -msgstr "Şununla bağlanıldı {0}" - -#: View/Helper/UserHelper.php:216 -msgid "Connect with {0}" -msgstr "Şununla bağlan {0}" diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php deleted file mode 100644 index 2e021884d..000000000 --- a/src/Mailer/UsersMailer.php +++ /dev/null @@ -1,81 +0,0 @@ -setHidden(['password', 'token_expires', 'api_token']); - $subject = __d('CakeDC/Users', 'Your account validation link'); - $this - ->setTo($user['email']) - ->setSubject($firstName . $subject) - ->setViewVars($user->toArray()) - ->setTemplate('CakeDC/Users.validation'); - } - - /** - * Send the reset password email to the user - * - * @param EntityInterface $user User entity - * - * @return void - */ - protected function resetPassword(EntityInterface $user) - { - $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - $subject = __d('CakeDC/Users', '{0}Your reset password link', $firstName); - // un-hide the token to be able to send it in the email content - $user->setHidden(['password', 'token_expires', 'api_token']); - - $this - ->setTo($user['email']) - ->setSubject($subject) - ->setViewVars($user->toArray()) - ->setTemplate('CakeDC/Users.resetPassword'); - } - - /** - * Send account validation email to the user - * - * @param EntityInterface $user User entity - * @param EntityInterface $socialAccount SocialAccount entity - * - * @return void - */ - protected function socialAccountValidation(EntityInterface $user, EntityInterface $socialAccount) - { - $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - // note: we control the space after the username in the previous line - $subject = __d('CakeDC/Users', '{0}Your social account validation link', $firstName); - $this - ->setTo($user['email']) - ->setSubject($subject) - ->setViewVars(compact('user', 'socialAccount')) - ->setTemplate('CakeDC/Users.socialAccountValidation'); - } -} diff --git a/src/Model/Behavior/AuthFinderBehavior.php b/src/Model/Behavior/AuthFinderBehavior.php deleted file mode 100644 index ef51d1fc9..000000000 --- a/src/Model/Behavior/AuthFinderBehavior.php +++ /dev/null @@ -1,62 +0,0 @@ -where([$this->_table->aliasField('active') => 1]); - - return $query; - } - - /** - * Custom finder to log in users - * - * @param Query $query Query object to modify - * @param array $options Query options - * @return Query - * @throws \BadMethodCallException - */ - public function findAuth(Query $query, array $options = []) - { - $identifier = Hash::get($options, 'username'); - if (empty($identifier)) { - throw new \BadMethodCallException(__d('CakeDC/Users', 'Missing \'username\' in options data')); - } - $where = $query->clause('where') ?: []; - $query - ->where(function ($exp) use ($identifier, $where) { - $or = $exp->or_([$this->_table->aliasField('email') => $identifier]); - - return $or->add($where); - }, [], true) - ->find('active', $options); - - return $query; - } -} diff --git a/src/Model/Behavior/BaseTokenBehavior.php b/src/Model/Behavior/BaseTokenBehavior.php deleted file mode 100644 index 1e6207159..000000000 --- a/src/Model/Behavior/BaseTokenBehavior.php +++ /dev/null @@ -1,59 +0,0 @@ -updateToken($tokenExpiration); - } else { - $user['active'] = true; - $user['activation_date'] = new Time(); - } - - return $user; - } - - /** - * Remove user token for validation - * - * @param EntityInterface $user user object. - * @return EntityInterface - */ - protected function _removeValidationToken(EntityInterface $user) - { - $user->token = null; - $user->token_expires = null; - $result = $this->_table->save($user); - - return $result; - } -} diff --git a/src/Model/Behavior/LinkSocialBehavior.php b/src/Model/Behavior/LinkSocialBehavior.php deleted file mode 100644 index 68f48608c..000000000 --- a/src/Model/Behavior/LinkSocialBehavior.php +++ /dev/null @@ -1,141 +0,0 @@ -_table->SocialAccounts->getAlias(); - $socialAccount = $this->_table->SocialAccounts->find() - ->where([ - $alias . '.reference' => $reference, - $alias . '.provider' => Hash::get($data, 'provider') - ])->first(); - - if ($socialAccount && $user->id !== $socialAccount->user_id) { - $user->setErrors([ - 'social_accounts' => [ - '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') - ] - ]); - - return $user; - } - - return $this->createOrUpdateSocialAccount($user, $data, $socialAccount); - } - - /** - * Create or update a new social account linking to the user. - * - * @param EntityInterface $user User to link. - * @param array $data Social account information. - * @param EntityInterface $socialAccount to update or create. - * - * @return EntityInterface - */ - protected function createOrUpdateSocialAccount(EntityInterface $user, $data, $socialAccount) - { - if (!$socialAccount) { - $socialAccount = $this->_table->SocialAccounts->newEntity(); - } - - $data['user_id'] = $user->id; - $socialAccount = $this->populateSocialAccount($socialAccount, $data); - - $result = $this->_table->SocialAccounts->save($socialAccount); - - $accounts = (array)$user->social_accounts; - $found = false; - foreach ($accounts as $key => $account) { - if ($account->id == $socialAccount->id) { - $accounts[$key] = $socialAccount; - $found = true; - break; - } - } - - if (!$found) { - $accounts[] = $socialAccount; - } - $user->social_accounts = $accounts; - - if ($result && !$result->getErrors()) { - return $user; - } - - return $user; - } - - /** - * Populate the social account - * - * @param EntityInterface $socialAccount to populate. - * @param array $data Social account information. - * - * @return EntityInterface - */ - protected function populateSocialAccount($socialAccount, $data) - { - $accountData = $socialAccount->toArray(); - $accountData['username'] = Hash::get($data, 'username'); - $accountData['reference'] = Hash::get($data, 'id'); - $accountData['avatar'] = Hash::get($data, 'avatar'); - $accountData['link'] = Hash::get($data, 'link'); - $accountData['avatar'] = str_replace('normal', 'square', $accountData['avatar']); - $accountData['description'] = Hash::get($data, 'bio'); - $accountData['token'] = Hash::get($data, 'credentials.token'); - $accountData['token_secret'] = Hash::get($data, 'credentials.secret'); - $accountData['user_id'] = Hash::get($data, 'user_id'); - $accountData['token_expires'] = null; - $expires = Hash::get($data, 'credentials.expires'); - if (!empty($expires)) { - $expiresTime = new Time(); - $accountData['token_expires'] = $expiresTime->setTimestamp($expires)->format('Y-m-d H:i:s'); - } - - $accountData['data'] = serialize(Hash::get($data, 'raw')); - $accountData['active'] = true; - - $socialAccount = $this->_table->SocialAccounts->patchEntity($socialAccount, $accountData); - //ensure provider is present in Entity - $socialAccount['provider'] = Hash::get($data, 'provider'); - - return $socialAccount; - } -} diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php deleted file mode 100644 index 2c08a0a1e..000000000 --- a/src/Model/Behavior/PasswordBehavior.php +++ /dev/null @@ -1,159 +0,0 @@ -_getUser($reference); - - if (empty($user)) { - throw new UserNotFoundException(__d('CakeDC/Users', "User not found")); - } - if (Hash::get($options, 'checkActive')) { - if ($user->active) { - throw new UserAlreadyActiveException(__d('CakeDC/Users', "User account already validated")); - } - $user->active = false; - $user->activation_date = null; - } - if (Hash::get($options, 'ensureActive')) { - if (!$user['active']) { - throw new UserNotActiveException(__d('CakeDC/Users', "User not active")); - } - } - $user->updateToken($expiration); - $saveResult = $this->_table->save($user); - if (Hash::get($options, 'sendEmail')) { - switch (Hash::get($options, 'type')) { - case 'email': - $this->_sendValidationEmail($user); - break; - case 'password': - $this->_sendResetPasswordEmail($user); - break; - } - } - - return $saveResult; - } - - /** - * Send the reset password related email link - * - * @param EntityInterface $user user - * @return void - */ - protected function _sendResetPasswordEmail($user) - { - $this - ->getMailer(Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users') - ->send('resetPassword', [$user]); - } - - /** - * Wrapper for mailer - * - * @param EntityInterface $user user - * @return void - */ - protected function _sendValidationEmail($user) - { - $mailer = Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users'; - $this - ->getMailer($mailer) - ->send('validation', [$user]); - } - - /** - * Get the user by email or username - * - * @param string $reference reference could be either an email or username - * @return mixed user entity if found - */ - protected function _getUser($reference) - { - return $this->_table->findByUsernameOrEmail($reference, $reference)->first(); - } - - /** - * Change password method - * - * @param EntityInterface $user user data. - * @throws WrongPasswordException - * @return mixed - */ - public function changePassword(EntityInterface $user) - { - try { - $currentUser = $this->_table->get($user->id, [ - 'contain' => [] - ]); - } catch (RecordNotFoundException $e) { - throw new UserNotFoundException(__d('CakeDC/Users', "User not found")); - } - - if (!empty($user->current_password)) { - if (!$user->checkPassword($user->current_password, $currentUser->password)) { - throw new WrongPasswordException(__d('CakeDC/Users', 'The current password does not match')); - } - if ($user->current_password === $user->password_confirm) { - throw new WrongPasswordException(__d( - 'CakeDC/Users', - 'You cannot use the current password as the new one' - )); - } - } - $user = $this->_table->save($user); - if (!empty($user)) { - $user = $this->_removeValidationToken($user); - } - - return $user; - } -} diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php deleted file mode 100644 index 6700fb9f7..000000000 --- a/src/Model/Behavior/RegisterBehavior.php +++ /dev/null @@ -1,210 +0,0 @@ -validateEmail = (bool)Configure::read('Users.Email.validate'); - $this->useTos = (bool)Configure::read('Users.Tos.required'); - } - - /** - * Registers an user. - * - * @param EntityInterface $user User information - * @param array $data User information - * @param array $options ['tokenExpiration] - * @return bool|EntityInterface - */ - public function register($user, $data, $options) - { - $validateEmail = Hash::get($options, 'validate_email'); - $tokenExpiration = Hash::get($options, 'token_expiration'); - $user = $this->_table->patchEntity( - $user, - $data, - ['validate' => Hash::get($options, 'validator') ?: $this->getRegisterValidators($options)] - ); - $user['role'] = Configure::read('Users.Registration.defaultRole') ?: 'user'; - $user->validated = false; - //@todo move updateActive to afterSave? - $user = $this->_updateActive($user, $validateEmail, $tokenExpiration); - $this->_table->isValidateEmail = $validateEmail; - $userSaved = $this->_table->save($user); - if ($userSaved && $validateEmail) { - $this->_sendValidationEmail($user); - } - - return $userSaved; - } - - /** - * Validates token and return user - * - * @param string $token toke to be validated. - * @param null $callback function that will be returned. - * @throws TokenExpiredException when token has expired. - * @throws UserNotFoundException when user isn't found. - * @return EntityInterface $user - */ - public function validate($token, $callback = null) - { - $user = $this->_table->find() - ->select(['token_expires', 'id', 'active', 'token']) - ->where(['token' => $token]) - ->first(); - if (empty($user)) { - throw new UserNotFoundException(__d('CakeDC/Users', "User not found for the given token and email.")); - } - if ($user->tokenExpired()) { - throw new TokenExpiredException(__d('CakeDC/Users', "Token has already expired user with no token")); - } - if (!method_exists($this, $callback)) { - return $user; - } - - return $this->_table->{$callback}($user); - } - - /** - * Activates an user - * - * @param EntityInterface $user user object. - * @return mixed User entity or bool false if the user could not be activated - * @throws UserAlreadyActiveException - */ - public function activateUser(EntityInterface $user) - { - if ($user->active) { - throw new UserAlreadyActiveException(__d('CakeDC/Users', "User account already validated")); - } - $user->activation_date = new \DateTime(); - $user->token_expires = null; - $user->active = true; - $result = $this->_table->save($user); - - return $result; - } - - /** - * buildValidator - * - * @param Event $event event - * @param Validator $validator validator - * @param string $name name - * @return Validator - */ - public function buildValidator(Event $event, Validator $validator, $name) - { - if ($name === 'default') { - return $this->_emailValidator($validator, $this->validateEmail); - } - - return $validator; - } - - /** - * Email validator - * - * @param Validator $validator Validator instance. - * @param bool $validateEmail true when email needs to be required - * @return Validator - */ - protected function _emailValidator(Validator $validator, $validateEmail) - { - $this->validateEmail = $validateEmail; - $validator - ->add('email', 'valid', ['rule' => 'email']) - ->notEmpty('email', __d('Users', 'This field is required'), function ($context) { - return $this->validateEmail; - }); - - return $validator; - } - - /** - * Tos validator - * - * @param Validator $validator Validator instance. - * @return Validator - */ - protected function _tosValidator(Validator $validator) - { - $validator - ->requirePresence('tos', 'create') - ->notEmpty('tos'); - - return $validator; - } - - /** - * Returns the list of validators - * - * @param array $options Array of options ['validate_email' => true/false, 'use_tos' => true/false] - * @return Validator - */ - public function getRegisterValidators($options) - { - $validateEmail = Hash::get($options, 'validate_email'); - $useTos = Hash::get($options, 'use_tos'); - - $validator = $this->_table->validationDefault(new Validator()); - $validator = $this->_table->validationRegister($validator); - if ($useTos) { - $validator = $this->_tosValidator($validator); - } - - if ($validateEmail) { - $validator = $this->_emailValidator($validator, $validateEmail); - } - - return $validator; - } - - /** - * Wrapper for mailer - * - * @param EntityInterface $user user - * @return void - */ - protected function _sendValidationEmail($user) - { - $mailer = Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users'; - $this - ->getMailer($mailer) - ->send('validation', [$user]); - } -} diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php deleted file mode 100644 index 1ab405ab3..000000000 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ /dev/null @@ -1,152 +0,0 @@ -_table->belongsTo('Users', [ - 'foreignKey' => 'user_id', - 'joinType' => 'INNER', - 'className' => Configure::read('Users.table') - ]); - } - - /** - * After save callback - * - * @param Event $event event - * @param Entity $entity entity - * @param \ArrayObject $options options - * @return mixed - */ - public function afterSave(Event $event, Entity $entity, $options) - { - if ($entity->active) { - return true; - } - $user = $this->_table->Users->find()->where(['Users.id' => $entity->user_id, 'Users.active' => true])->first(); - if (empty($user)) { - return true; - } - - return $this->sendSocialValidationEmail($entity, $user); - } - - /** - * Send social validation email to the user - * - * @param EntityInterface $socialAccount social account - * @param EntityInterface $user user - * @return void - */ - protected function sendSocialValidationEmail(EntityInterface $socialAccount, EntityInterface $user) - { - return $this - ->getMailer(Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users') - ->send('socialAccountValidation', [$user, $socialAccount]); - } - - /** - * Validates the social account - * - * @param string $provider provider - * @param string $reference reference - * @param string $token token - * @throws RecordNotFoundException - * @throws AccountAlreadyActiveException - * @return User - */ - public function validateAccount($provider, $reference, $token) - { - $socialAccount = $this->_table->find() - ->select(['id', 'provider', 'reference', 'active', 'token']) - ->where(['provider' => $provider, 'reference' => $reference]) - ->first(); - - if (!empty($socialAccount) && $socialAccount->token === $token) { - if ($socialAccount->active) { - throw new AccountAlreadyActiveException(__d('CakeDC/Users', "Account already validated")); - } - } else { - throw new RecordNotFoundException(__d('CakeDC/Users', "Account not found for the given token and email.")); - } - - return $this->_activateAccount($socialAccount); - } - - /** - * Validates the social account - * - * @param string $provider provider - * @param string $reference reference - * @throws RecordNotFoundException - * @throws AccountAlreadyActiveException - * @return User - */ - public function resendValidation($provider, $reference) - { - $socialAccount = $this->_table->find() - ->where(['provider' => $provider, 'reference' => $reference]) - ->contain('Users') - ->first(); - - if (!empty($socialAccount)) { - if ($socialAccount->active) { - throw new AccountAlreadyActiveException(__d('CakeDC/Users', "Account already validated")); - } - } else { - throw new RecordNotFoundException(__d('CakeDC/Users', "Account not found for the given token and email.")); - } - - return $this->sendSocialValidationEmail($socialAccount, $socialAccount->user); - } - - /** - * Activates an account - * - * @param SocialAccount $socialAccount social account - * @return EntityInterface - */ - protected function _activateAccount($socialAccount) - { - $socialAccount->active = true; - $result = $this->_table->save($socialAccount); - - return $result; - } -} diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php deleted file mode 100644 index 8fbc82416..000000000 --- a/src/Model/Behavior/SocialBehavior.php +++ /dev/null @@ -1,261 +0,0 @@ -_username = $config['username']; - } - - parent::initialize($config); - } - - /** - * Performs social login - * - * @param array $data Array social login. - * @param array $options Array option data. - * @throws InvalidArgumentException - * @throws UserNotActiveException - * @throws AccountNotActiveException - * @return bool|EntityInterface|mixed - */ - public function socialLogin(array $data, array $options) - { - $reference = Hash::get($data, 'id'); - $existingAccount = $this->_table->SocialAccounts->find() - ->where([ - 'SocialAccounts.reference' => $reference, - 'SocialAccounts.provider' => Hash::get($data, 'provider') - ]) - ->contain(['Users']) - ->first(); - if (empty($existingAccount->user)) { - $user = $this->_createSocialUser($data, $options); - if (!empty($user->social_accounts[0])) { - $existingAccount = $user->social_accounts[0]; - } else { - //@todo: what if we don't have a social account after createSocialUser? - throw new InvalidArgumentException(__d('CakeDC/Users', 'Unable to login user with reference {0}', $reference)); - } - } else { - $user = $existingAccount->user; - } - if (!empty($existingAccount)) { - if (!$existingAccount->active) { - throw new AccountNotActiveException([ - $existingAccount->provider, - $existingAccount->reference - ]); - } - if (!$user->active) { - throw new UserNotActiveException([ - $existingAccount->provider, - $existingAccount->$user - ]); - } - } - - return $user; - } - - /** - * Creates social user, populate the user data based on the social login data first and save it - * - * @param array $data Array social user. - * @param array $options Array option data. - * @throws MissingEmailException - * @return bool|EntityInterface|mixed result of the save operation - */ - protected function _createSocialUser($data, $options = []) - { - $useEmail = Hash::get($options, 'use_email'); - $validateEmail = Hash::get($options, 'validate_email'); - $tokenExpiration = Hash::get($options, 'token_expiration'); - $existingUser = null; - $email = Hash::get($data, 'email'); - if ($useEmail && empty($email)) { - throw new MissingEmailException(__d('CakeDC/Users', 'Email not present')); - } else { - $existingUser = $this->_table->find() - ->where([$this->_table->aliasField('email') => $email]) - ->first(); - } - - $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); - - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_SOCIAL_LOGIN_USER_CREATE, [ - 'userEntity' => $user, - ]); - if ($event->result instanceof EntityInterface) { - $user = $event->result; - } - - $this->_table->isValidateEmail = $validateEmail; - $result = $this->_table->save($user); - - return $result; - } - - /** - * Build new user entity either by using an existing user or extracting the data from the social login - * data to create a new one - * - * @param array $data Array social login. - * @param EntityInterface $existingUser user data. - * @param string $useEmail email to use. - * @param string $validateEmail email to validate. - * @param string $tokenExpiration token_expires data. - * @return EntityInterface - * @todo refactor - */ - protected function _populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration) - { - $accountData['username'] = Hash::get($data, 'username'); - $accountData['reference'] = Hash::get($data, 'id'); - $accountData['avatar'] = Hash::get($data, 'avatar'); - $accountData['link'] = Hash::get($data, 'link'); - - $accountData['avatar'] = str_replace('normal', 'square', $accountData['avatar']); - $accountData['description'] = Hash::get($data, 'bio'); - $accountData['token'] = Hash::get($data, 'credentials.token'); - $accountData['token_secret'] = Hash::get($data, 'credentials.secret'); - $expires = Hash::get($data, 'credentials.expires'); - if (!empty($expires)) { - $expiresTime = new DateTime(); - $accountData['token_expires'] = $expiresTime->setTimestamp($expires)->format('Y-m-d H:i:s'); - } else { - $accountData['token_expires'] = null; - } - $accountData['data'] = serialize(Hash::get($data, 'raw')); - $accountData['active'] = true; - - $dataValidated = Hash::get($data, 'validated'); - - if (empty($existingUser)) { - $firstName = Hash::get($data, 'first_name'); - $lastName = Hash::get($data, 'last_name'); - if (!empty($firstName) && !empty($lastName)) { - $userData['first_name'] = $firstName; - $userData['last_name'] = $lastName; - } else { - $name = explode(' ', Hash::get($data, 'full_name')); - $userData['first_name'] = Hash::get($name, 0); - array_shift($name); - $userData['last_name'] = implode(' ', $name); - } - $userData['username'] = Hash::get($data, 'username'); - $username = Hash::get($userData, 'username'); - if (empty($username)) { - $dataEmail = Hash::get($data, 'email'); - if (!empty($dataEmail)) { - $email = explode('@', $dataEmail); - $userData['username'] = Hash::get($email, 0); - } else { - $firstName = Hash::get($userData, 'first_name'); - $lastName = Hash::get($userData, 'last_name'); - $userData['username'] = strtolower($firstName . $lastName); - $userData['username'] = preg_replace('/[^A-Za-z0-9]/i', '', Hash::get($userData, 'username')); - } - } - - $userData['username'] = $this->generateUniqueUsername(Hash::get($userData, 'username')); - if ($useEmail) { - $userData['email'] = Hash::get($data, 'email'); - if (empty($dataValidated)) { - $accountData['active'] = false; - } - } - - $userData['password'] = $this->randomString(); - $userData['avatar'] = Hash::get($data, 'avatar'); - $userData['validated'] = !empty($dataValidated); - $userData['tos_date'] = date("Y-m-d H:i:s"); - $userData['gender'] = Hash::get($data, 'gender'); - $userData['social_accounts'][] = $accountData; - - $user = $this->_table->newEntity($userData); - $user = $this->_updateActive($user, false, $tokenExpiration); - } else { - if ($useEmail && empty($dataValidated)) { - $accountData['active'] = false; - } - $user = $existingUser; - } - $socialAccount = $this->_table->SocialAccounts->newEntity($accountData); - //ensure provider is present in Entity - $socialAccount['provider'] = Hash::get($data, 'provider'); - $user['social_accounts'] = [$socialAccount]; - $user['role'] = Configure::read('Users.Registration.defaultRole') ?: 'user'; - - return $user; - } - - /** - * Checks if username exists and generate a new one - * - * @param string $username username data. - * @return string - */ - public function generateUniqueUsername($username) - { - $i = 0; - while (true) { - $existingUsername = $this->_table->find() - ->where([$this->_table->aliasField($this->_username) => $username]) - ->count(); - if ($existingUsername > 0) { - $username = $username . $i; - $i++; - continue; - } - break; - } - - return $username; - } -} diff --git a/src/Model/Entity/SocialAccount.php b/src/Model/Entity/SocialAccount.php deleted file mode 100644 index 9c6f421ec..000000000 --- a/src/Model/Entity/SocialAccount.php +++ /dev/null @@ -1,41 +0,0 @@ - true, - 'id' => false, - ]; - - /** - * Fields that are excluded from JSON an array versions of the entity. - * - * @var array - */ - protected $_hidden = [ - 'token', - 'token_secret', - 'token_expires', - ]; -} diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php deleted file mode 100644 index e4c8b8520..000000000 --- a/src/Model/Entity/User.php +++ /dev/null @@ -1,163 +0,0 @@ - true, - 'id' => false, - 'is_superuser' => false, - 'role' => false, - ]; - - /** - * Fields that are excluded from JSON an array versions of the entity. - * - * @var array - */ - protected $_hidden = [ - 'password', - 'token', - 'token_expires', - 'api_token', - ]; - - /** - * @param string $password password that will be set. - * @return bool|string - */ - protected function _setPassword($password) - { - return $this->hashPassword($password); - } - - /** - * @param string $password password that will be confirm. - * @return bool|string - */ - protected function _setConfirmPassword($password) - { - return $this->hashPassword($password); - } - - /** - * @param string $tos tos option. It will be set the tos_date - * @return bool - */ - protected function _setTos($tos) - { - if ((bool)$tos === true) { - $this->set('tos_date', Time::now()); - } - - return $tos; - } - - /** - * Hash a password using the configured password hasher, - * use DefaultPasswordHasher if no one was configured - * - * @param string $password password to be hashed - * @return mixed - */ - public function hashPassword($password) - { - $PasswordHasher = $this->getPasswordHasher(); - - return $PasswordHasher->hash($password); - } - - /** - * Return the configured Password Hasher - * - * @return mixed - */ - public function getPasswordHasher() - { - $passwordHasher = Configure::read('Users.passwordHasher'); - if (!class_exists($passwordHasher)) { - $passwordHasher = '\Cake\Auth\DefaultPasswordHasher'; - } - - return new $passwordHasher; - } - - /** - * Checks if a password is correctly hashed - * - * @param string $password password that will be check. - * @param string $hashedPassword hash used to check password. - * @return bool - */ - public function checkPassword($password, $hashedPassword) - { - $PasswordHasher = $this->getPasswordHasher(); - - return $PasswordHasher->check($password, $hashedPassword); - } - - /** - * Returns if the token has already expired - * - * @return bool - */ - public function tokenExpired() - { - if (empty($this->token_expires)) { - return true; - } - - return new Time($this->token_expires) < Time::now(); - } - - /** - * Getter for user avatar - * - * @return string|null avatar - */ - protected function _getAvatar() - { - $avatar = null; - if (!empty($this->_properties['social_accounts'][0])) { - $avatar = $this->_properties['social_accounts'][0]['avatar']; - } - - return $avatar; - } - - /** - * Generate token_expires and token in a user - * @param int $tokenExpiration seconds to expire the token from Now - * @return void - */ - public function updateToken($tokenExpiration = 0) - { - $expiration = new Time('now'); - $this->token_expires = $expiration->addSeconds($tokenExpiration); - $this->token = bin2hex(Security::randomBytes(16)); - } -} diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php deleted file mode 100644 index 1363dd399..000000000 --- a/src/Model/Table/SocialAccountsTable.php +++ /dev/null @@ -1,133 +0,0 @@ -setTable('social_accounts'); - $this->setDisplayField('id'); - $this->setPrimaryKey('id'); - $this->addBehavior('Timestamp'); - $this->addBehavior('CakeDC/Users.SocialAccount'); - } - - /** - * Default validation rules. - * - * @param Validator $validator Validator instance. - * @return Validator - */ - public function validationDefault(Validator $validator) - { - $validator - ->add('id', 'valid', ['rule' => 'uuid']) - ->allowEmpty('id', 'create'); - - $validator - ->requirePresence('provider', 'create') - ->notEmpty('provider'); - - $validator - ->allowEmpty('username'); - - $validator - ->requirePresence('reference', 'create') - ->notEmpty('reference'); - - $validator - ->requirePresence('link', 'create') - ->notEmpty('reference'); - - $validator - ->allowEmpty('avatar'); - - $validator - ->allowEmpty('description'); - - $validator - ->requirePresence('token', 'create') - ->notEmpty('token'); - - $validator - ->allowEmpty('token_secret'); - - $validator - ->add('token_expires', 'valid', ['rule' => 'datetime']) - ->allowEmpty('token_expires'); - - $validator - ->add('active', 'valid', ['rule' => 'boolean']) - ->requirePresence('active', 'create') - ->notEmpty('active'); - - $validator - ->requirePresence('data', 'create') - ->notEmpty('data'); - - return $validator; - } - - /** - * Returns a rules checker object that will be used for validating - * application integrity. - * - * @param RulesChecker $rules The rules object to be modified. - * @return RulesChecker - */ - public function buildRules(RulesChecker $rules) - { - $rules->add($rules->existsIn(['user_id'], 'Users')); - - return $rules; - } - - /** - * Finder for active social accounts - * - * @param Query $query query - * @return \Cake\ORM\Query - */ - public function findActive(Query $query) - { - return $query->where([ - $this->aliasField('active') => true - ]); - } -} diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php deleted file mode 100644 index d8e1919f7..000000000 --- a/src/Model/Table/UsersTable.php +++ /dev/null @@ -1,185 +0,0 @@ -setTable('users'); - $this->setDisplayField('username'); - $this->setPrimaryKey('id'); - $this->addBehavior('Timestamp'); - $this->addBehavior('CakeDC/Users.Register'); - $this->addBehavior('CakeDC/Users.Password'); - $this->addBehavior('CakeDC/Users.Social'); - $this->addBehavior('CakeDC/Users.LinkSocial'); - $this->addBehavior('CakeDC/Users.AuthFinder'); - $this->hasMany('SocialAccounts', [ - 'foreignKey' => 'user_id', - 'className' => 'CakeDC/Users.SocialAccounts' - ]); - } - - /** - * Adds some rules for password confirm - * @param Validator $validator Cake validator object. - * @return Validator - */ - public function validationPasswordConfirm(Validator $validator) - { - $validator - ->requirePresence('password_confirm', 'create') - ->notEmpty('password_confirm'); - - $validator - ->requirePresence('password', 'create') - ->notEmpty('password') - ->add('password', [ - 'password_confirm_check' => [ - 'rule' => ['compareWith', 'password_confirm'], - 'message' => __d('CakeDC/Users', 'Your password does not match your confirm password. Please try again'), - 'allowEmpty' => false - ]]); - - return $validator; - } - - /** - * Adds rules for current password - * - * @param Validator $validator Cake validator object. - * @return Validator - */ - public function validationCurrentPassword(Validator $validator) - { - $validator - ->notEmpty('current_password'); - - return $validator; - } - - /** - * Default validation rules. - * - * @param Validator $validator Validator instance. - * @return Validator - */ - public function validationDefault(Validator $validator) - { - $validator - ->allowEmpty('id', 'create'); - - $validator - ->requirePresence('username', 'create') - ->notEmpty('username'); - - $validator - ->requirePresence('password', 'create') - ->notEmpty('password'); - - $validator - ->allowEmpty('first_name'); - - $validator - ->allowEmpty('last_name'); - - $validator - ->allowEmpty('token'); - - $validator - ->add('token_expires', 'valid', ['rule' => 'datetime']) - ->allowEmpty('token_expires'); - - $validator - ->allowEmpty('api_token'); - - $validator - ->add('activation_date', 'valid', ['rule' => 'datetime']) - ->allowEmpty('activation_date'); - - $validator - ->add('tos_date', 'valid', ['rule' => 'datetime']) - ->allowEmpty('tos_date'); - - return $validator; - } - - /** - * Wrapper for all validation rules for register - * @param Validator $validator Cake validator object. - * - * @return Validator - */ - public function validationRegister(Validator $validator) - { - $validator = $this->validationDefault($validator); - $validator = $this->validationPasswordConfirm($validator); - - return $validator; - } - - /** - * Returns a rules checker object that will be used for validating - * application integrity. - * - * @param RulesChecker $rules The rules object to be modified. - * @return RulesChecker - */ - public function buildRules(RulesChecker $rules) - { - $rules->add($rules->isUnique(['username']), '_isUnique', [ - 'errorField' => 'username', - 'message' => __d('CakeDC/Users', 'Username already exists') - ]); - - if ($this->isValidateEmail) { - $rules->add($rules->isUnique(['email']), '_isUnique', [ - 'errorField' => 'email', - 'message' => __d('CakeDC/Users', 'Email already exists') - ]); - } - - return $rules; - } -} diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php deleted file mode 100644 index 292dc71b3..000000000 --- a/src/Shell/UsersShell.php +++ /dev/null @@ -1,404 +0,0 @@ -Users = $this->loadModel(Configure::read('Users.table')); - } - - /** - * - * @return ConsoleOptionParser - */ - public function getOptionParser() - { - $parser = parent::getOptionParser(); - $parser->setDescription(__d('CakeDC/Users', 'Utilities for CakeDC Users Plugin')) - ->addSubcommand('activateUser', [ - 'help' => __d('CakeDC/Users', 'Activate an specific user') - ]) - ->addSubcommand('addSuperuser', [ - 'help' => __d('CakeDC/Users', 'Add a new superadmin user for testing purposes') - ]) - ->addSubcommand('addUser', [ - 'help' => __d('CakeDC/Users', 'Add a new user') - ]) - ->addSubcommand('changeRole', [ - 'help' => __d('CakeDC/Users', 'Change the role for an specific user') - ]) - ->addSubcommand('deactivateUser', [ - 'help' => __d('CakeDC/Users', 'Deactivate an specific user') - ]) - ->addSubcommand('deleteUser', [ - 'help' => __d('CakeDC/Users', 'Delete an specific user') - ]) - ->addSubcommand('passwordEmail', [ - 'help' => __d('CakeDC/Users', 'Reset the password via email') - ]) - ->addSubcommand('resetAllPasswords', [ - 'help' => __d('CakeDC/Users', 'Reset the password for all users') - ]) - ->addSubcommand('resetPassword', [ - 'help' => __d('CakeDC/Users', 'Reset the password for an specific user') - ]) - ->addOptions([ - 'username' => ['short' => 'u', 'help' => 'The username for the new user'], - 'password' => ['short' => 'p', 'help' => 'The password for the new user'], - 'email' => ['short' => 'e', 'help' => 'The email for the new user'], - 'role' => ['short' => 'r', 'help' => 'The role for the new user'] - ]); - - return $parser; - } - - /** - * Add a new user - * - * @return void - */ - public function addUser() - { - $this->_createUser(['role' => Configure::read('Users.Registration.defaultRole') ?: 'user']); - } - - /** - * Add a new superadmin user - * - * @return void - */ - public function addSuperuser() - { - $this->_createUser([ - 'username' => 'superadmin', - 'role' => 'superuser', - 'is_superuser' => true - ]); - } - - /** - * Reset password for all user - * - * Arguments: - * - * - Password to be set - * - * @return void - */ - public function resetAllPasswords() - { - $password = Hash::get($this->args, 0); - if (empty($password)) { - $this->abort(__d('CakeDC/Users', 'Please enter a password.')); - } - $hashedPassword = $this->_generatedHashedPassword($password); - $this->Users->updateAll(['password' => $hashedPassword], ['id IS NOT NULL']); - $this->out(__d('CakeDC/Users', 'Password changed for all users')); - $this->out(__d('CakeDC/Users', 'New password: {0}', $password)); - } - - /** - * Reset password for a user - * - * Arguments: - * - * - Username - * - Password to be set - * - * @return void - */ - public function resetPassword() - { - $username = Hash::get($this->args, 0); - $password = Hash::get($this->args, 1); - if (empty($username)) { - $this->abort(__d('CakeDC/Users', 'Please enter a username.')); - } - if (empty($password)) { - $this->abort(__d('CakeDC/Users', 'Please enter a password.')); - } - $data = [ - 'password' => $password - ]; - $this->_updateUser($username, $data); - $this->out(__d('CakeDC/Users', 'Password changed for user: {0}', $username)); - $this->out(__d('CakeDC/Users', 'New password: {0}', $password)); - } - - /** - * Change role for a user - * - * Arguments: - * - * - Username - * - Role to be set - * - * @return void - */ - public function changeRole() - { - $username = Hash::get($this->args, 0); - $role = Hash::get($this->args, 1); - if (empty($username)) { - $this->abort(__d('CakeDC/Users', 'Please enter a username.')); - } - if (empty($role)) { - $this->abort(__d('CakeDC/Users', 'Please enter a role.')); - } - $data = [ - 'role' => $role - ]; - $savedUser = $this->_updateUser($username, $data); - $this->out(__d('CakeDC/Users', 'Role changed for user: {0}', $username)); - $this->out(__d('CakeDC/Users', 'New role: {0}', $savedUser->role)); - } - - /** - * Activate an specific user - * - * Arguments: - * - * - Username - * - * @return void - */ - public function activateUser() - { - $user = $this->_changeUserActive(true); - $this->out(__d('CakeDC/Users', 'User was activated: {0}', $user->username)); - } - - /** - * De-activate an specific user - * - * Arguments: - * - * - Username - * - * @return void - */ - public function deactivateUser() - { - $user = $this->_changeUserActive(false); - $this->out(__d('CakeDC/Users', 'User was de-activated: {0}', $user->username)); - } - - /** - * Reset password via email for user - * - * @return void - */ - public function passwordEmail() - { - $reference = Hash::get($this->args, 0); - if (empty($reference)) { - $this->abort(__d('CakeDC/Users', 'Please enter a username or email.')); - } - $resetUser = $this->Users->resetToken($reference, [ - 'expiration' => Configure::read('Users.Token.expiration'), - 'checkActive' => false, - 'sendEmail' => true, - ]); - if ($resetUser) { - $msg = __d('CakeDC/Users', 'Please ask the user to check the email to continue with password reset process'); - $this->out($msg); - } else { - $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); - $this->abort($msg); - } - } - - /** - * Change user active field - * - * @param bool $active active value - * @return bool - */ - protected function _changeUserActive($active) - { - $username = Hash::get($this->args, 0); - if (empty($username)) { - $this->abort(__d('CakeDC/Users', 'Please enter a username.')); - } - $data = [ - 'active' => $active - ]; - - return $this->_updateUser($username, $data); - } - - /** - * Create a new user or superuser - * - * @param array $template template with deafault user values - * @return void - */ - protected function _createUser($template) - { - if (!empty($this->params['username'])) { - $username = $this->params['username']; - } else { - $username = !empty($template['username']) ? - $template['username'] : $this->_generateRandomUsername(); - } - - $password = (empty($this->params['password']) ? - $this->_generateRandomPassword() : $this->params['password']); - $email = (empty($this->params['email']) ? - $username . '@example.com' : $this->params['email']); - $role = (empty($this->params['role']) ? - $template['role'] : $this->params['role']); - - $user = [ - 'username' => $this->Users->generateUniqueUsername($username), - 'email' => $email, - 'password' => $password, - 'active' => 1, - ]; - - $userEntity = $this->Users->newEntity($user); - $userEntity->is_superuser = empty($template['is_superuser']) ? - false : $template['is_superuser']; - $userEntity->role = $role; - $savedUser = $this->Users->save($userEntity); - - if (!empty($savedUser)) { - if ($savedUser->is_superuser) { - $this->out(__d('CakeDC/Users', 'Superuser added:')); - } else { - $this->out(__d('CakeDC/Users', 'User added:')); - } - $this->out(__d('CakeDC/Users', 'Id: {0}', $savedUser->id)); - $this->out(__d('CakeDC/Users', 'Username: {0}', $savedUser->username)); - $this->out(__d('CakeDC/Users', 'Email: {0}', $savedUser->email)); - $this->out(__d('CakeDC/Users', 'Role: {0}', $savedUser->role)); - $this->out(__d('CakeDC/Users', 'Password: {0}', $password)); - } else { - $this->out(__d('CakeDC/Users', 'User could not be added:')); - - collection($userEntity->getErrors())->each(function ($error, $field) { - $this->out(__d('CakeDC/Users', 'Field: {0} Error: {1}', $field, implode(',', $error))); - }); - } - } - - /** - * Update user by username - * - * @param string $username username - * @param array $data data - * @return bool - */ - protected function _updateUser($username, $data) - { - $user = $this->Users->find()->where(['username' => $username])->first(); - if (empty($user)) { - $this->abort(__d('CakeDC/Users', 'The user was not found.')); - } - $user = $this->Users->patchEntity($user, $data); - collection($data)->filter(function ($value, $field) use ($user) { - return !$user->isAccessible($field); - })->each(function ($value, $field) use (&$user) { - $user->{$field} = $value; - }); - $savedUser = $this->Users->save($user); - - return $savedUser; - } - - /** - * Delete an specific user and associated social accounts - * - * @return void - */ - public function deleteUser() - { - $username = Hash::get($this->args, 0); - if (empty($username)) { - $this->abort(__d('CakeDC/Users', 'Please enter a username.')); - } - $user = $this->Users->find()->where(['username' => $username])->first(); - if (isset($this->Users->SocialAccounts)) { - $this->Users->SocialAccounts->deleteAll(['user_id' => $user->id]); - } - $deleteUser = $this->Users->delete($user); - if (!$deleteUser) { - $this->abort(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); - } - $this->out(__d('CakeDC/Users', 'The user {0} was deleted successfully', $username)); - } - - /** - * Generates a random password. - * - * @return string - */ - protected function _generateRandomPassword() - { - return str_replace('-', '', Text::uuid()); - } - - /** - * Generates a random username based on a list of preexisting ones. - * - * @return string - */ - protected function _generateRandomUsername() - { - return $this->_usernameSeed[array_rand($this->_usernameSeed)]; - } - - /** - * Hash a password - * - * @param string $password password - * @return string - */ - protected function _generatedHashedPassword($password) - { - return (new User)->hashPassword($password); - } - //add filters LIKE in username and email to some tasks - // --force to ignore "you are about to do X to Y users" -} diff --git a/src/Template/Email/html/reset_password.ctp b/src/Template/Email/html/reset_password.ctp deleted file mode 100644 index f6055a1d4..000000000 --- a/src/Template/Email/html/reset_password.ctp +++ /dev/null @@ -1,35 +0,0 @@ - true, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'resetPassword', - isset($token) ? $token : '' -]; -?> -

- , -

-

- Html->link(__d('CakeDC/Users', 'Reset your password here'), $activationUrl) ?> -

-

-Url->build($activationUrl) -) ?> -

-

- , -

diff --git a/src/Template/Email/html/social_account_validation.ctp b/src/Template/Email/html/social_account_validation.ctp deleted file mode 100644 index acef3fbc5..000000000 --- a/src/Template/Email/html/social_account_validation.ctp +++ /dev/null @@ -1,40 +0,0 @@ - - -

- , -

-

- true, - 'plugin' => 'CakeDC/Users', - 'controller' => 'SocialAccounts', - 'action' => 'validateAccount', - $socialAccount['provider'], - $socialAccount['reference'], - $socialAccount['token'], - ]; - echo $this->Html->link($text, $activationUrl); - ?> -

-

-Url->build($activationUrl) -) ?> -

-

- , -

diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp deleted file mode 100644 index 8a1840468..000000000 --- a/src/Template/Email/html/validation.ctp +++ /dev/null @@ -1,35 +0,0 @@ - true, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'validateEmail', - isset($token) ? $token : '' -]; -?> -

- , -

-

- Html->link(__d('CakeDC/Users', 'Activate your account here'), $activationUrl) ?> -

-

-Url->build($activationUrl) -) ?> -

-

- , -

diff --git a/src/Template/Email/text/reset_password.ctp b/src/Template/Email/text/reset_password.ctp deleted file mode 100644 index 96f001565..000000000 --- a/src/Template/Email/text/reset_password.ctp +++ /dev/null @@ -1,29 +0,0 @@ - true, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'resetPassword', - isset($token) ? $token : '' -]; -?> -, - -Url->build($activationUrl) -) ?> - -, - diff --git a/src/Template/Email/text/social_account_validation.ctp b/src/Template/Email/text/social_account_validation.ctp deleted file mode 100644 index 87e2d6813..000000000 --- a/src/Template/Email/text/social_account_validation.ctp +++ /dev/null @@ -1,31 +0,0 @@ - true, - 'plugin' => 'CakeDC/Users', - 'controller' => 'SocialAccounts', - 'action' => 'validateAccount', - $socialAccount['provider'], - $socialAccount['reference'], - $socialAccount['token'], -]; -?> -, - -Url->build($activationUrl) -) ?> - -, - diff --git a/src/Template/Email/text/validation.ctp b/src/Template/Email/text/validation.ctp deleted file mode 100644 index ecf9d96a8..000000000 --- a/src/Template/Email/text/validation.ctp +++ /dev/null @@ -1,29 +0,0 @@ - true, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'validateEmail', - isset($token) ? $token : '' -]; -?> -, - -Url->build($activationUrl) -) ?> - -, - diff --git a/src/Template/Layout/Email/html/default.ctp b/src/Template/Layout/Email/html/default.ctp deleted file mode 100644 index b0c828681..000000000 --- a/src/Template/Layout/Email/html/default.ctp +++ /dev/null @@ -1,20 +0,0 @@ - - - - - <?= $this->fetch('title') ?> - - - fetch('content') ?> - - diff --git a/src/Template/Layout/Email/text/default.ctp b/src/Template/Layout/Email/text/default.ctp deleted file mode 100644 index 686aa84ab..000000000 --- a/src/Template/Layout/Email/text/default.ctp +++ /dev/null @@ -1,13 +0,0 @@ - -fetch('content'); diff --git a/src/Template/Users/add.ctp b/src/Template/Users/add.ctp deleted file mode 100644 index 751b2f3c6..000000000 --- a/src/Template/Users/add.ctp +++ /dev/null @@ -1,36 +0,0 @@ - -
-

-
    -
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • -
-
-
- Form->create(${$tableAlias}); ?> -
- - Form->control('username', ['label' => __d('CakeDC/Users', 'Username')]); - echo $this->Form->control('email', ['label' => __d('CakeDC/Users', 'Email')]); - echo $this->Form->control('password', ['label' => __d('CakeDC/Users', 'Password')]); - echo $this->Form->control('first_name', ['label' => __d('CakeDC/Users', 'First name')]); - echo $this->Form->control('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); - echo $this->Form->control('active', [ - 'type' => 'checkbox', - 'label' => __d('CakeDC/Users', 'Active') - ]); - ?> -
- Form->button(__d('CakeDC/Users', 'Submit')) ?> - Form->end() ?> -
diff --git a/src/Template/Users/change_password.ctp b/src/Template/Users/change_password.ctp deleted file mode 100644 index 339f2fc65..000000000 --- a/src/Template/Users/change_password.ctp +++ /dev/null @@ -1,27 +0,0 @@ -
- Flash->render('auth') ?> - Form->create($user) ?> -
- - - Form->control('current_password', [ - 'type' => 'password', - 'required' => true, - 'label' => __d('CakeDC/Users', 'Current password')]); - ?> - - Form->control('password', [ - 'type' => 'password', - 'required' => true, - 'label' => __d('CakeDC/Users', 'New password')]); - ?> - Form->control('password_confirm', [ - 'type' => 'password', - 'required' => true, - 'label' => __d('CakeDC/Users', 'Confirm password')]); - ?> - -
- Form->button(__d('CakeDC/Users', 'Submit')); ?> - Form->end() ?> -
\ No newline at end of file diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp deleted file mode 100644 index 91794b822..000000000 --- a/src/Template/Users/edit.ctp +++ /dev/null @@ -1,77 +0,0 @@ - -
-

-
    -
  • - Form->postLink( - __d('CakeDC/Users', 'Delete'), - ['action' => 'delete', $Users->id], - ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $Users->id)] - ); - ?> -
  • -
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • -
-
-
- Form->create($Users); ?> -
- - Form->control('username', ['label' => __d('CakeDC/Users', 'Username')]); - echo $this->Form->control('email', ['label' => __d('CakeDC/Users', 'Email')]); - echo $this->Form->control('first_name', ['label' => __d('CakeDC/Users', 'First name')]); - echo $this->Form->control('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); - echo $this->Form->control('token', ['label' => __d('CakeDC/Users', 'Token')]); - echo $this->Form->control('token_expires', [ - 'label' => __d('CakeDC/Users', 'Token expires') - ]); - echo $this->Form->control('api_token', [ - 'label' => __d('CakeDC/Users', 'API token') - ]); - echo $this->Form->control('activation_date', [ - 'label' => __d('CakeDC/Users', 'Activation date') - ]); - echo $this->Form->control('tos_date', [ - 'label' => __d('CakeDC/Users', 'TOS date') - ]); - echo $this->Form->control('active', [ - 'label' => __d('CakeDC/Users', 'Active') - ]); - ?> -
- Form->button(__d('CakeDC/Users', 'Submit')) ?> - Form->end() ?> - -
- Reset Google Authenticator - Form->postLink( - __d('CakeDC/Users', 'Reset Google Authenticator Token'), [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'resetGoogleAuthenticator', $Users->id - ], [ - 'class' => 'btn btn-danger', - 'confirm' => __d( - 'CakeDC/Users', - 'Are you sure you want to reset token for user "{0}"?', $Users->username - ) - ]); - ?> -
- -
diff --git a/src/Template/Users/index.ctp b/src/Template/Users/index.ctp deleted file mode 100644 index 6c9e49871..000000000 --- a/src/Template/Users/index.ctp +++ /dev/null @@ -1,55 +0,0 @@ - -
-

-
    -
  • Html->link(__d('CakeDC/Users', 'New {0}', $tableAlias), ['action' => 'add']) ?>
  • -
-
-
- - - - - - - - - - - - - - - - - - - - - - -
Paginator->sort('username', __d('CakeDC/Users', 'Username')) ?>Paginator->sort('email', __d('CakeDC/Users', 'Email')) ?>Paginator->sort('first_name', __d('CakeDC/Users', 'First name')) ?>Paginator->sort('last_name', __d('CakeDC/Users', 'Last name')) ?>
username) ?>email) ?>first_name) ?>last_name) ?> - Html->link(__d('CakeDC/Users', 'View'), ['action' => 'view', $user->id]) ?> - Html->link(__d('CakeDC/Users', 'Change password'), ['action' => 'changePassword', $user->id]) ?> - Html->link(__d('CakeDC/Users', 'Edit'), ['action' => 'edit', $user->id]) ?> - Form->postLink(__d('CakeDC/Users', 'Delete'), ['action' => 'delete', $user->id], ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $user->id)]) ?> -
-
-
    - Paginator->prev('< ' . __d('CakeDC/Users', 'previous')) ?> - Paginator->numbers() ?> - Paginator->next(__d('CakeDC/Users', 'next') . ' >') ?> -
-

Paginator->counter() ?>

-
-
diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp deleted file mode 100644 index 5e08f7cd6..000000000 --- a/src/Template/Users/login.ctp +++ /dev/null @@ -1,50 +0,0 @@ - -
- Flash->render('auth') ?> - Form->create() ?> -
- - Form->control('username', ['label' => __d('CakeDC/Users', 'Username'), 'required' => true]) ?> - Form->control('password', ['label' => __d('CakeDC/Users', 'Password'), 'required' => true]) ?> - User->addReCaptcha(); - } - if (Configure::read('Users.RememberMe.active')) { - echo $this->Form->control(Configure::read('Users.Key.Data.rememberMe'), [ - 'type' => 'checkbox', - 'label' => __d('CakeDC/Users', 'Remember me'), - 'checked' => Configure::read('Users.RememberMe.checked') - ]); - } - ?> - Html->link(__d('CakeDC/Users', 'Register'), ['action' => 'register']); - } - if (Configure::read('Users.Email.required')) { - if ($registrationActive) { - echo ' | '; - } - echo $this->Html->link(__d('CakeDC/Users', 'Reset Password'), ['action' => 'requestResetPassword']); - } - ?> -
- User->socialLoginList()); ?> - Form->button(__d('CakeDC/Users', 'Login')); ?> - Form->end() ?> -
diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp deleted file mode 100644 index 8b59d9ee2..000000000 --- a/src/Template/Users/profile.ctp +++ /dev/null @@ -1,78 +0,0 @@ - -
-

Html->image( - empty($user->avatar) ? $avatarPlaceholder : $user->avatar, - ['width' => '180', 'height' => '180'] - ); ?>

-

- Html->tag( - 'span', - __d('CakeDC/Users', '{0} {1}', $user->first_name, $user->last_name), - ['class' => 'full_name'] - ) - ?> -

- - Html->link(__d('CakeDC/Users', 'Change Password'), ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'changePassword']); ?> -
-
-
-

username) ?>

-
-

email) ?>

- User->socialConnectLinkList($user->social_accounts) ?> - social_accounts)): - ?> -
- - - - - - - - - - social_accounts as $socialAccount): - $escapedUsername = h($socialAccount->username); - $linkText = empty($escapedUsername) ? __d('CakeDC/Users', 'Link to {0}', h($socialAccount->provider)) : h($socialAccount->username) - ?> - - - - - - - -
Html->image( - $socialAccount->avatar, - ['width' => '90', 'height' => '90'] - ) ?> - provider) ?>Html->link( - $linkText, - $socialAccount->link, - ['target' => '_blank'] - ) ?>
- -
-
-
diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp deleted file mode 100644 index 5a62448a0..000000000 --- a/src/Template/Users/register.ctp +++ /dev/null @@ -1,38 +0,0 @@ - -
- Form->create($user); ?> -
- - Form->control('username', ['label' => __d('CakeDC/Users', 'Username')]); - echo $this->Form->control('email', ['label' => __d('CakeDC/Users', 'Email')]); - echo $this->Form->control('password', ['label' => __d('CakeDC/Users', 'Password')]); - echo $this->Form->control('password_confirm', [ - 'type' => 'password', - 'label' => __d('CakeDC/Users', 'Confirm password') - ]); - echo $this->Form->control('first_name', ['label' => __d('CakeDC/Users', 'First name')]); - echo $this->Form->control('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); - if (Configure::read('Users.Tos.required')) { - echo $this->Form->control('tos', ['type' => 'checkbox', 'label' => __d('CakeDC/Users', 'Accept TOS conditions?'), 'required' => true]); - } - if (Configure::read('Users.reCaptcha.registration')) { - echo $this->User->addReCaptcha(); - } - ?> -
- Form->button(__d('CakeDC/Users', 'Submit')) ?> - Form->end() ?> -
diff --git a/src/Template/Users/request_reset_password.ctp b/src/Template/Users/request_reset_password.ctp deleted file mode 100644 index e406ff573..000000000 --- a/src/Template/Users/request_reset_password.ctp +++ /dev/null @@ -1,10 +0,0 @@ -
- Flash->render('auth') ?> - Form->create('User') ?> -
- - Form->control('reference') ?> -
- Form->button(__d('CakeDC/Users', 'Submit')); ?> - Form->end() ?> -
diff --git a/src/Template/Users/resend_token_validation.ctp b/src/Template/Users/resend_token_validation.ctp deleted file mode 100644 index 2d2680fbe..000000000 --- a/src/Template/Users/resend_token_validation.ctp +++ /dev/null @@ -1,22 +0,0 @@ - -
- Form->create($user); ?> -
- - Form->control('reference', ['label' => __d('CakeDC/Users', 'Email or username')]); - ?> -
- Form->button(__d('CakeDC/Users', 'Submit')) ?> - Form->end() ?> -
diff --git a/src/Template/Users/social_email.ctp b/src/Template/Users/social_email.ctp deleted file mode 100644 index b0a272b6d..000000000 --- a/src/Template/Users/social_email.ctp +++ /dev/null @@ -1,21 +0,0 @@ - -
- Flash->render() ?> - Form->create('User') ?> -
- - Form->control('email') ?> -
- Form->button(__d('CakeDC/Users', 'Submit')); ?> - Form->end() ?> -
diff --git a/src/Template/Users/verify.ctp b/src/Template/Users/verify.ctp deleted file mode 100644 index f1f7d2524..000000000 --- a/src/Template/Users/verify.ctp +++ /dev/null @@ -1,20 +0,0 @@ -
-
-
-
- Form->create() ?> - - Flash->render('auth') ?> - Flash->render() ?> -
- -

- - Form->control('code', ['required' => true, 'label' => __d('CakeDC/Users', 'Verification Code')]) ?> -
- Form->button(__d('CakeDC/Users', ' Verify'), ['class' => 'btn btn-primary']); ?> - Form->end() ?> -
-
-
-
diff --git a/src/Template/Users/view.ctp b/src/Template/Users/view.ctp deleted file mode 100644 index d2e21bf7a..000000000 --- a/src/Template/Users/view.ctp +++ /dev/null @@ -1,90 +0,0 @@ - -
-

-
    -
  • Html->link(__d('CakeDC/Users', 'Edit User'), ['action' => 'edit', $Users->id]) ?>
  • -
  • Form->postLink( - __d('CakeDC/Users', 'Delete User'), - ['action' => 'delete', $Users->id], - ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $Users->id)] - ) ?>
  • -
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • -
  • Html->link(__d('CakeDC/Users', 'New User'), ['action' => 'add']) ?>
  • -
-
-
-

id) ?>

-
-
-
-

id) ?>

-
-

username) ?>

-
-

email) ?>

-
-

first_name) ?>

-
-

last_name) ?>

-
-

role) ?>

-
-

token) ?>

-
-

api_token) ?>

-
-
-
-

Number->format($Users->active) ?>

-
-
-
-

token_expires) ?>

-
-

activation_date) ?>

-
-

tos_date) ?>

-
-

created) ?>

-
-

modified) ?>

-
-
-
- diff --git a/src/Traits/RandomStringTrait.php b/src/Traits/RandomStringTrait.php deleted file mode 100644 index 668a0c828..000000000 --- a/src/Traits/RandomStringTrait.php +++ /dev/null @@ -1,30 +0,0 @@ -isAuthorized($url)) { - return Hash::get($options, 'before') . - parent::link($title, $url, $linkOptions) . - Hash::get($options, 'after'); - } - - return false; - } - - /** - * Returns true if the target url is authorized for the logged in user - * - * @param string|array|null $url url that the user is making request. - * @return bool - */ - public function isAuthorized($url = null) - { - $event = new Event(UsersAuthComponent::EVENT_IS_AUTHORIZED, $this, ['url' => $url]); - $result = EventManager::instance()->dispatch($event); - - return $result->result; - } -} diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php deleted file mode 100644 index ba23e5c0c..000000000 --- a/src/View/Helper/UserHelper.php +++ /dev/null @@ -1,254 +0,0 @@ -Html->tag('i', '', [ - 'class' => 'fa fa-' . strtolower($name), - ]); - - if (isset($options['title'])) { - $providerTitle = $options['title']; - } else { - $providerTitle = Hash::get($options, 'label') . ' ' . Inflector::camelize($name); - } - - $providerClass = 'btn btn-social btn-' . strtolower($name) . ((Hash::get($options, 'class')) ? ' ' . Hash::get($options, 'class') : ''); - - return $this->Html->link($icon . $providerTitle, "/auth/$name", [ - 'escape' => false, 'class' => $providerClass, - ]); - } - - /** - * All available Social Login Icons - * - * @param array $providerOptions Provider link options. - * @return array Links to Social Login Urls - */ - public function socialLoginList(array $providerOptions = []) - { - if (!Configure::read('Users.Social.login')) { - return []; - } - $outProviders = []; - $providers = Configure::read('OAuth.providers'); - foreach ($providers as $provider => $options) { - if (!empty($options['options']['redirectUri']) && - !empty($options['options']['clientId']) && - !empty($options['options']['clientSecret']) - ) { - if (isset($providerOptions[$provider])) { - $options['options'] = Hash::merge($options['options'], $providerOptions[$provider]); - } - - $outProviders[] = $this->socialLogin($provider, $options['options']); - } - } - - return $outProviders; - } - - /** - * Logout link - * - * @param null $message logout message info. - * @param array $options Array with option data. - * @return string - */ - public function logout($message = null, $options = []) - { - return $this->AuthLink->link(empty($message) ? __d('CakeDC/Users', 'Logout') : $message, [ - 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout', - ], $options); - } - - /** - * Welcome display - * @return mixed - */ - public function welcome() - { - $userId = $this->request->getSession()->read('Auth.User.id'); - if (empty($userId)) { - return; - } - - $profileUrl = Configure::read('Users.Profile.route'); - $label = __d('CakeDC/Users', 'Welcome, {0}', $this->AuthLink->link($this->request->getSession()->read('Auth.User.first_name') ?: $this->request->getSession()->read('Auth.User.username'), $profileUrl)); - - return $this->Html->tag('span', $label, ['class' => 'welcome']); - } - - /** - * Add reCaptcha script - * @return void - */ - public function addReCaptchaScript() - { - $this->Html->script('https://www.google.com/recaptcha/api.js', [ - 'block' => 'script', - ]); - } - - /** - * Add reCaptcha to the form - * @return mixed - */ - public function addReCaptcha() - { - if (!Configure::read('Users.reCaptcha.key')) { - return $this->Html->tag('p', __d('CakeDC/Users', 'reCaptcha is not configured! Please configure Users.reCaptcha.key')); - } - $this->addReCaptchaScript(); - $this->Form->unlockField('g-recaptcha-response'); - - return $this->Html->tag('div', '', [ - 'class' => 'g-recaptcha', - 'data-sitekey' => Configure::read('Users.reCaptcha.key'), - 'data-theme' => Configure::read('Users.reCaptcha.theme') ?: 'light', - 'data-size' => Configure::read('Users.reCaptcha.size') ?: 'normal', - 'data-tabindex' => Configure::read('Users.reCaptcha.tabindex') ?: '3', - ]); - } - - /** - * Generate a link if the target url is authorized for the logged in user - * - * @deprecated Since 3.2.1. Use AuthLinkHelper::link() instead - * - * @param string $title link's title. - * @param string|array|null $url url that the user is making request. - * @param array $options Array with option data. - * @return string - */ - public function link($title, $url = null, array $options = []) - { - trigger_error( - 'UserHelper::link() deprecated since 3.2.1. Use AuthLinkHelper::link() instead', - E_USER_DEPRECATED - ); - - return $this->AuthLink->link($title, $url, $options); - } - - /** - * Returns true if the target url is authorized for the logged in user - * - * @deprecated Since 3.2.1. Use AuthLinkHelper::link() instead - * - * @param string|array|null $url url that the user is making request. - * @return bool - */ - public function isAuthorized($url = null) - { - trigger_error( - 'UserHelper::isAuthorized() deprecated since 3.2.1. Use AuthLinkHelper::isAuthorized() instead', - E_USER_DEPRECATED - ); - - return $this->AuthLink->isAuthorized($url); - } - /** - * Create links for all social providers enabled social link (connect) - * - * @param string $name Provider name in lowercase - * @param array $provider Provider configuration - * @param bool $isConnected User is connected with this provider - * - * @return string - */ - public function socialConnectLink($name, $provider, $isConnected = false) - { - $linkClass = 'btn btn-social btn-' . strtolower($name) . ((Hash::get($provider['options'], 'class')) ? ' ' . Hash::get($provider['options'], 'class') : ''); - if ($isConnected) { - $title = __d('CakeDC/Users', 'Connected with {0}', Inflector::camelize($name)); - - return "
$title"; - } - - $title = __d('CakeDC/Users', 'Connect with {0}', Inflector::camelize($name)); - - return $this->Html->link( - " $title", - "/link-social/$name", - [ - 'escape' => false, - 'class' => $linkClass, - ] - ); - } - - /** - * Create links for all social providers enabled social link (connect) - * - * @param array $socialAccounts All social accounts connected by a user. - * - * @return string - */ - public function socialConnectLinkList($socialAccounts = []) - { - if (!Configure::read('Users.Social.login')) { - return ""; - } - $html = ""; - $connectedProviders = array_map( - function ($item) { - return strtolower($item->provider); - }, - (array)$socialAccounts - ); - - $providers = Configure::read('OAuth.providers'); - foreach ($providers as $name => $provider) { - if (!empty($provider['options']['callbackLinkSocialUri']) && - !empty($provider['options']['linkSocialUri']) && - !empty($provider['options']['clientId']) && - !empty($provider['options']['clientSecret']) - ) { - $html .= $this->socialConnectLink($name, $provider, in_array($name, $connectedProviders)); - } - } - - return $html; - } -} diff --git a/tests/App/Controller/AppController.php b/tests/App/Controller/AppController.php deleted file mode 100644 index 4afebdf12..000000000 --- a/tests/App/Controller/AppController.php +++ /dev/null @@ -1,33 +0,0 @@ -loadComponent('Flash'); - // $this->loadComponent('CakeDC/Users.UsersAuth'); - $this->loadComponent('RequestHandler'); - } -} diff --git a/tests/App/Mailer/OverrideMailer.php b/tests/App/Mailer/OverrideMailer.php deleted file mode 100644 index 3affd4dc0..000000000 --- a/tests/App/Mailer/OverrideMailer.php +++ /dev/null @@ -1,34 +0,0 @@ -setSubject('This is the new subject'); - $this->setTemplate('custom-template-in-app-namespace'); - } -} diff --git a/tests/App/Template/Email/text/custom_template_in_app_namespace.ctp b/tests/App/Template/Email/text/custom_template_in_app_namespace.ctp deleted file mode 100644 index 1619a4eb2..000000000 --- a/tests/App/Template/Email/text/custom_template_in_app_namespace.ctp +++ /dev/null @@ -1 +0,0 @@ -some custom template here \ No newline at end of file diff --git a/tests/App/Template/Layout/Email/html/default.ctp b/tests/App/Template/Layout/Email/html/default.ctp deleted file mode 100644 index 21c7e0044..000000000 --- a/tests/App/Template/Layout/Email/html/default.ctp +++ /dev/null @@ -1,2 +0,0 @@ -fetch('content'); diff --git a/tests/App/Template/Layout/Email/text/default.ctp b/tests/App/Template/Layout/Email/text/default.ctp deleted file mode 100644 index 21c7e0044..000000000 --- a/tests/App/Template/Layout/Email/text/default.ctp +++ /dev/null @@ -1,2 +0,0 @@ -fetch('content'); diff --git a/tests/Fixture/PostsFixture.php b/tests/Fixture/PostsFixture.php deleted file mode 100644 index 257e98be2..000000000 --- a/tests/Fixture/PostsFixture.php +++ /dev/null @@ -1,60 +0,0 @@ - ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], - 'title' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'user_id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], - ], - '_options' => [ - 'engine' => 'InnoDB', - 'collation' => 'utf8_general_ci' - ], - ]; - // @codingStandardsIgnoreEnd - - /** - * Records - * - * @var array - */ - public $records = [ - [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'title' => 'post-1', - 'user_id' => '00000000-0000-0000-0000-000000000001', - ], - [ - 'id' => '00000000-0000-0000-0000-000000000002', - 'title' => 'post-2', - 'user_id' => '00000000-0000-0000-0000-000000000002', - ], - ]; -} diff --git a/tests/Fixture/PostsUsersFixture.php b/tests/Fixture/PostsUsersFixture.php deleted file mode 100644 index 8b5948f5d..000000000 --- a/tests/Fixture/PostsUsersFixture.php +++ /dev/null @@ -1,60 +0,0 @@ - ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], - 'user_id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'post_id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], - ], - '_options' => [ - 'engine' => 'InnoDB', - 'collation' => 'utf8_general_ci' - ], - ]; - // @codingStandardsIgnoreEnd - - /** - * Records - * - * @var array - */ - public $records = [ - [ - 'id' => '00000000-0000-0000-0000-000000000011', - 'user_id' => '00000000-0000-0000-0000-000000000001', - 'post_id' => '00000000-0000-0000-0000-000000000001', - ], - [ - 'id' => '00000000-0000-0000-0000-000000000012', - 'user_id' => '00000000-0000-0000-0000-000000000002', - 'post_id' => '00000000-0000-0000-0000-000000000002', - ], - ]; -} diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php deleted file mode 100644 index 48a966eda..000000000 --- a/tests/Fixture/SocialAccountsFixture.php +++ /dev/null @@ -1,141 +0,0 @@ - ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], - 'user_id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'provider' => ['type' => 'string', 'length' => 255, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => null], - 'username' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'reference' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'avatar' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'description' => ['type' => 'text', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], - 'token' => ['type' => 'string', 'length' => 500, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'token_secret' => ['type' => 'string', 'length' => 500, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'token_expires' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], - 'active' => ['type' => 'boolean', 'length' => null, 'null' => false, 'default' => true, 'comment' => '', 'precision' => null], - 'data' => ['type' => 'text', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], - 'created' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], - 'modified' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], - ], - '_options' => [ - 'engine' => 'InnoDB', - 'collation' => 'utf8_general_ci' - ], - ]; - // @codingStandardsIgnoreEnd - - /** - * Records - * - * @var array - */ - public $records = [ - [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'user_id' => '00000000-0000-0000-0000-000000000001', - 'provider' => 'Facebook', - 'username' => 'user-1-fb', - 'reference' => 'reference-1-1234', - 'avatar' => 'Lorem ipsum dolor sit amet', - 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', - 'token' => 'token-1234', - 'token_secret' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-05-22 21:52:44', - 'active' => false, - 'data' => '', - 'created' => '2015-05-22 21:52:44', - 'modified' => '2015-05-22 21:52:44' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000002', - 'user_id' => '00000000-0000-0000-0000-000000000001', - 'provider' => 'Twitter', - 'username' => 'user-1-tw', - 'reference' => 'reference-1-1234', - 'avatar' => 'Lorem ipsum dolor sit amet', - 'description' => '', - 'token' => 'token-1234', - 'token_secret' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-05-22 21:52:44', - 'active' => true, - 'data' => '', - 'created' => '2015-05-22 21:52:44', - 'modified' => '2015-05-22 21:52:44' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000003', - 'user_id' => '00000000-0000-0000-0000-000000000002', - 'provider' => 'Facebook', - 'username' => 'user-2-fb', - 'reference' => 'reference-2-1', - 'avatar' => 'Lorem ipsum dolor sit amet', - 'description' => '', - 'token' => 'token-reference-2-1', - 'token_secret' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-05-22 21:52:44', - 'active' => true, - 'data' => '', - 'created' => '2015-05-22 21:52:44', - 'modified' => '2015-05-22 21:52:44' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000004', - 'user_id' => '00000000-0000-0000-0000-000000000003', - 'provider' => 'Twitter', - 'username' => 'user-2-tw', - 'reference' => 'reference-2-2', - 'avatar' => 'Lorem ipsum dolor sit amet', - 'description' => '', - 'token' => 'token-reference-2-2', - 'token_secret' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-05-22 21:52:44', - 'active' => false, - 'data' => '', - 'created' => '2015-05-22 21:52:44', - 'modified' => '2015-05-22 21:52:44' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000005', - 'user_id' => '00000000-0000-0000-0000-000000000004', - 'provider' => 'Twitter', - 'username' => 'user-2-tw', - 'reference' => 'reference-2-2', - 'avatar' => 'Lorem ipsum dolor sit amet', - 'description' => '', - 'token' => 'token-reference-2-2', - 'token_secret' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-05-22 21:52:44', - 'active' => false, - 'data' => '', - 'created' => '2015-05-22 21:52:44', - 'modified' => '2015-05-22 21:52:44' - ], - ]; -} diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php deleted file mode 100644 index d0256aed8..000000000 --- a/tests/Fixture/UsersFixture.php +++ /dev/null @@ -1,267 +0,0 @@ - ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], - 'username' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'email' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'password' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'first_name' => ['type' => 'string', 'length' => 50, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'last_name' => ['type' => 'string', 'length' => 50, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'token' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'token_expires' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], - 'api_token' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'activation_date' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], - 'secret' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], - 'secret_verified' => ['type' => 'boolean', 'length' => null, 'null' => true, 'default' => false, 'comment' => '', 'precision' => null], - 'tos_date' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], - 'active' => ['type' => 'boolean', 'length' => null, 'null' => false, 'default' => true, 'comment' => '', 'precision' => null], - 'is_superuser' => ['type' => 'boolean', 'length' => null, 'unsigned' => false, 'null' => false, 'default' => false, 'comment' => '', 'precision' => null, 'autoIncrement' => null], - 'role' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => 'user', 'comment' => '', 'precision' => null, 'fixed' => null], - 'created' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], - 'modified' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], - ], - '_options' => [ - 'engine' => 'InnoDB', - 'collation' => 'utf8_general_ci' - ], - ]; - // @codingStandardsIgnoreEnd - - /** - * Records - * - * @var array - */ - public $records = [ - [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'username' => 'user-1', - 'email' => 'user-1@test.com', - 'password' => '12345', - 'first_name' => 'first1', - 'last_name' => 'last1', - 'token' => 'ae93ddbe32664ce7927cf0c5c5a5e59d', - 'token_expires' => '2035-06-24 17:33:54', - 'api_token' => 'yyy', - 'activation_date' => '2015-06-24 17:33:54', - 'secret' => 'yyy', - 'secret_verified' => false, - 'tos_date' => '2015-06-24 17:33:54', - 'active' => false, - 'is_superuser' => true, - 'role' => 'admin', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000002', - 'username' => 'user-2', - 'email' => 'user-2@test.com', - 'password' => '12345', - 'first_name' => 'user', - 'last_name' => 'second', - 'token' => '6614f65816754310a5f0553436dd89e9', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'xxx', - 'activation_date' => '2015-06-24 17:33:54', - 'secret' => 'xxx', - 'secret_verified' => false, - 'tos_date' => '2015-06-24 17:33:54', - 'active' => true, - 'is_superuser' => true, - 'role' => 'admin', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000003', - 'username' => 'user-3', - 'email' => 'user-3@test.com', - 'password' => '12345', - 'first_name' => 'user', - 'last_name' => 'third', - 'token' => 'token-3', - 'token_expires' => '2030-06-20 17:33:54', - 'api_token' => 'xxx', - 'activation_date' => '2015-06-24 17:33:54', - 'secret' => 'xxx', - 'secret_verified' => true, - 'is_superuser' => true, - 'tos_date' => '2015-06-24 17:33:54', - 'active' => false, - 'is_superuser' => true, - 'role' => 'admin', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000004', - 'username' => 'user-4', - 'email' => '4@example.com', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'FirstName4', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'token-4', - 'token_expires' => '2030-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'secret' => 'Lorem ipsum dolor sit amet', - 'secret_verified' => true, - 'is_superuser' => false, - 'tos_date' => '2015-06-24 17:33:54', - 'active' => true, - 'is_superuser' => false, - 'role' => 'Lorem ipsum dolor sit amet', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000005', - 'username' => 'user-5', - 'email' => 'test@example.com', - 'password' => '12345', - 'first_name' => 'first-user-5', - 'last_name' => 'firts name 5', - 'token' => 'token-5', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => '', - 'activation_date' => '2015-06-24 17:33:54', - 'secret' => '', - 'secret_verified' => false, - 'tos_date' => '2015-06-24 17:33:54', - 'active' => true, - 'is_superuser' => false, - 'role' => 'user', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000006', - 'username' => 'user-6', - 'email' => '6@example.com', - 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', - 'first_name' => 'first-user-6', - 'last_name' => 'firts name 6', - 'token' => 'token-6', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => '', - 'activation_date' => '2015-06-24 17:33:54', - 'secret' => '', - 'secret_verified' => false, - 'tos_date' => '2015-06-24 17:33:54', - 'active' => true, - 'is_superuser' => false, - 'role' => 'user', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000007', - 'username' => 'Lorem ipsum dolor sit amet', - 'email' => 'Lorem ipsum dolor sit amet', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'Lorem ipsum dolor sit amet', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'secret' => 'Lorem ipsum dolor sit amet', - 'secret_verified' => false, - 'tos_date' => '2015-06-24 17:33:54', - 'active' => true, - 'is_superuser' => false, - 'role' => 'Lorem ipsum dolor sit amet', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000008', - 'username' => 'Lorem ipsum dolor sit amet', - 'email' => 'Lorem ipsum dolor sit amet', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'Lorem ipsum dolor sit amet', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'secret' => 'Lorem ipsum dolor sit amet', - 'secret_verified' => false, - 'tos_date' => '2015-06-24 17:33:54', - 'active' => true, - 'is_superuser' => false, - 'role' => 'Lorem ipsum dolor sit amet', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000009', - 'username' => 'Lorem ipsum dolor sit amet', - 'email' => 'Lorem ipsum dolor sit amet', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'Lorem ipsum dolor sit amet', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'secret' => 'Lorem ipsum dolor sit amet', - 'secret_verified' => false, - 'tos_date' => '2015-06-24 17:33:54', - 'active' => true, - 'is_superuser' => false, - 'role' => 'Lorem ipsum dolor sit amet', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - [ - 'id' => '00000000-0000-0000-0000-000000000010', - 'username' => 'Lorem ipsum dolor sit amet', - 'email' => 'Lorem ipsum dolor sit amet', - 'password' => 'Lorem ipsum dolor sit amet', - 'first_name' => 'Lorem ipsum dolor sit amet', - 'last_name' => 'Lorem ipsum dolor sit amet', - 'token' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-06-24 17:33:54', - 'api_token' => 'Lorem ipsum dolor sit amet', - 'activation_date' => '2015-06-24 17:33:54', - 'secret' => 'Lorem ipsum dolor sit amet', - 'secret_verified' => false, - 'tos_date' => '2015-06-24 17:33:54', - 'active' => true, - 'is_superuser' => false, - 'role' => 'Lorem ipsum dolor sit amet', - 'created' => '2015-06-24 17:33:54', - 'modified' => '2015-06-24 17:33:54' - ], - ]; -} diff --git a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php deleted file mode 100644 index 6f6be7d8c..000000000 --- a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php +++ /dev/null @@ -1,67 +0,0 @@ -assertFalse($Checker->isEnabled()); - - Configure::write('Users.GoogleAuthenticator.login', true); - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertTrue($Checker->isEnabled()); - - Configure::delete('Users.GoogleAuthenticator.login'); - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertTrue($Checker->isEnabled()); - } - - /** - * Test isRequired method - * - * @return void - */ - public function testIsRequired() - { - Configure::write('Users.GoogleAuthenticator.login', false); - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertFalse($Checker->isRequired(['id' => 10])); - - Configure::write('Users.GoogleAuthenticator.login', true); - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertTrue($Checker->isRequired(['id' => 10])); - - Configure::delete('Users.GoogleAuthenticator.login'); - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertTrue($Checker->isRequired(['id' => 10])); - - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertFalse($Checker->isRequired([])); - } -} diff --git a/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php b/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php deleted file mode 100644 index 5a44e7451..000000000 --- a/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php +++ /dev/null @@ -1,46 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php b/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php deleted file mode 100644 index 68d18bc24..000000000 --- a/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php +++ /dev/null @@ -1,46 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php b/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php deleted file mode 100644 index f182d9083..000000000 --- a/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php +++ /dev/null @@ -1,45 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php b/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php deleted file mode 100644 index e1eb1bb3d..000000000 --- a/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php +++ /dev/null @@ -1,46 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Auth/Social/Mapper/FacebookTest.php b/tests/TestCase/Auth/Social/Mapper/FacebookTest.php deleted file mode 100644 index 8c8ba9e85..000000000 --- a/tests/TestCase/Auth/Social/Mapper/FacebookTest.php +++ /dev/null @@ -1,91 +0,0 @@ - 'test-token', - 'expires' => 1490988496 - ]); - $rawData = [ - 'token' => $token, - 'id' => '1', - 'name' => 'Test User', - 'first_name' => 'Test', - 'last_name' => 'User', - 'email' => 'test@gmail.com', - 'hometown' => [ - 'id' => '108226049197930', - 'name' => 'Madrid' - ], - 'picture' => [ - 'data' => [ - 'url' => 'https://scontent.xx.fbcdn.net/v/test.jpg', - 'is_silhouette' => false - ] - ], - 'cover' => [ - 'source' => 'https://scontent.xx.fbcdn.net/v/test.jpg', - 'id' => '1' - ], - 'gender' => 'male', - 'locale' => 'en_US', - 'link' => 'https://www.facebook.com/app_scoped_user_id/1/', - 'timezone' => -5, - 'age_range' => [ - 'min' => 21 - ], - 'bio' => 'I am the best test user in the world.', - 'picture_url' => 'https://scontent.xx.fbcdn.net/v/test.jpg', - 'is_silhouette' => false, - 'cover_photo_url' => 'https://scontent.xx.fbcdn.net/v/test.jpg' - ]; - $providerMapper = new Facebook($rawData); - $user = $providerMapper(); - $this->assertEquals([ - 'id' => '1', - 'username' => null, - 'full_name' => 'Test User', - 'first_name' => 'Test', - 'last_name' => 'User', - 'email' => 'test@gmail.com', - 'avatar' => 'https://graph.facebook.com/1/picture?type=large', - 'gender' => 'male', - 'link' => 'https://www.facebook.com/app_scoped_user_id/1/', - 'bio' => 'I am the best test user in the world.', - 'locale' => 'en_US', - 'validated' => true, - 'credentials' => [ - 'token' => 'test-token', - 'secret' => null, - 'expires' => 1490988496 - ], - 'raw' => $rawData - ], $user); - } -} diff --git a/tests/TestCase/Auth/Social/Mapper/GoogleTest.php b/tests/TestCase/Auth/Social/Mapper/GoogleTest.php deleted file mode 100644 index 376e8273a..000000000 --- a/tests/TestCase/Auth/Social/Mapper/GoogleTest.php +++ /dev/null @@ -1,73 +0,0 @@ - 'test-token', - 'expires' => 1490988496 - ]); - $rawData = [ - 'token' => $token, - 'emails' => [['value' => 'test@gmail.com']], - 'id' => '1', - 'displayName' => 'Test User', - 'name' => [ - 'familyName' => 'User', - 'givenName' => 'Test' - ], - 'aboutMe' => 'I am the best test user in the world.', - 'url' => 'https://plus.google.com/+TestUser', - 'image' => [ - 'url' => 'https://lh3.googleusercontent.com/photo.jpg' - ] - ]; - $providerMapper = new Google($rawData); - $user = $providerMapper(); - $this->assertEquals([ - 'id' => '1', - 'username' => null, - 'full_name' => 'Test User', - 'first_name' => 'Test', - 'last_name' => 'User', - 'email' => 'test@gmail.com', - 'avatar' => 'https://lh3.googleusercontent.com/photo.jpg', - 'gender' => null, - 'link' => 'https://plus.google.com/+TestUser', - 'bio' => 'I am the best test user in the world.', - 'locale' => null, - 'validated' => true, - 'credentials' => [ - 'token' => 'test-token', - 'secret' => null, - 'expires' => 1490988496 - ], - 'raw' => $rawData - ], $user); - } -} diff --git a/tests/TestCase/Auth/Social/Mapper/InstagramTest.php b/tests/TestCase/Auth/Social/Mapper/InstagramTest.php deleted file mode 100644 index 7d3b05625..000000000 --- a/tests/TestCase/Auth/Social/Mapper/InstagramTest.php +++ /dev/null @@ -1,72 +0,0 @@ - 'test-token', - 'expires' => 1490988496 - ]); - $rawData = [ - 'token' => $token, - 'profile_picture' => 'https://scontent-lax3-2.cdninstagram.com/test.jpg', - 'username' => 'test', - 'id' => '1', - 'full_name' => '', - 'website' => '', - 'counts' => [ - 'followed_by' => 35, - 'media' => 1, - 'follows' => 44 - ], - 'bio' => '' - ]; - $providerMapper = new Instagram($rawData); - $user = $providerMapper(); - $this->assertEquals([ - 'id' => '1', - 'username' => 'test', - 'full_name' => '', - 'first_name' => null, - 'last_name' => null, - 'email' => null, - 'avatar' => 'https://scontent-lax3-2.cdninstagram.com/test.jpg', - 'gender' => null, - 'link' => 'https://instagram.com/test', - 'bio' => '', - 'locale' => null, - 'validated' => false, - 'credentials' => [ - 'token' => 'test-token', - 'secret' => null, - 'expires' => 1490988496 - ], - 'raw' => $rawData - ], $user); - } -} diff --git a/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php b/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php deleted file mode 100644 index 3f17e77a7..000000000 --- a/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php +++ /dev/null @@ -1,75 +0,0 @@ - 'test-token', - 'expires' => 1490988496 - ]); - $rawData = [ - 'token' => $token, - 'emailAddress' => 'test@gmail.com', - 'firstName' => 'Test', - 'headline' => 'The best test user in the world.', - 'id' => '1', - 'industry' => 'Computer Software', - 'lastName' => 'User', - 'location' => [ - 'country' => [ - 'code' => 'es' - ], - 'name' => 'Spain' - ], - 'pictureUrl' => 'https://media.licdn.com/mpr/mprx/test.jpg', - 'publicProfileUrl' => 'https://www.linkedin.com/in/test' - ]; - $providerMapper = new LinkedIn($rawData); - $user = $providerMapper(); - $this->assertEquals([ - 'id' => '1', - 'username' => null, - 'full_name' => null, - 'first_name' => 'Test', - 'last_name' => 'User', - 'email' => 'test@gmail.com', - 'avatar' => 'https://media.licdn.com/mpr/mprx/test.jpg', - 'gender' => null, - 'link' => 'https://www.linkedin.com/in/test', - 'bio' => 'The best test user in the world.', - 'locale' => null, - 'validated' => true, - 'credentials' => [ - 'token' => 'test-token', - 'secret' => null, - 'expires' => 1490988496 - ], - 'raw' => $rawData - ], $user); - } -} diff --git a/tests/TestCase/Auth/Social/Mapper/TwitterTest.php b/tests/TestCase/Auth/Social/Mapper/TwitterTest.php deleted file mode 100644 index d33aa343f..000000000 --- a/tests/TestCase/Auth/Social/Mapper/TwitterTest.php +++ /dev/null @@ -1,71 +0,0 @@ - '1', - 'nickname' => 'test', - 'name' => 'Test User', - 'firstName' => null, - 'lastName' => null, - 'email' => null, - 'location' => '', - 'description' => '', - 'imageUrl' => 'http://pbs.twimg.com/profile_images/test.jpeg', - 'urls' => [], - 'extra' => [], - 'token' => [ - 'accessToken' => 'test-token', - 'tokenSecret' => 'test-secret' - ] - ]; - $providerMapper = new Twitter($rawData); - $user = $providerMapper(); - $this->assertEquals([ - 'id' => '1', - 'username' => 'test', - 'full_name' => 'Test User', - 'first_name' => null, - 'last_name' => null, - 'email' => null, - 'avatar' => 'http://pbs.twimg.com/profile_images/test.jpeg', - 'gender' => null, - 'link' => 'https://twitter.com/test', - 'bio' => '', - 'locale' => null, - 'validated' => false, - 'credentials' => [ - 'token' => 'test-token', - 'secret' => 'test-secret', - 'expires' => null - ], - 'raw' => $rawData - ], $user); - } -} diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php deleted file mode 100644 index 14a5f72bb..000000000 --- a/tests/TestCase/Auth/SocialAuthenticateTest.php +++ /dev/null @@ -1,644 +0,0 @@ -Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - - $this->Token = $this->getMockBuilder('League\OAuth2\Client\Token\AccessToken') - ->setMethods(['getToken', 'getExpires']) - ->disableOriginalConstructor() - ->getMock(); - - $this->controller = $this->getMockBuilder('Cake\Controller\Controller') - ->setMethods(['failedSocialLogin', 'dispatchEvent']) - ->setConstructorArgs([$request, $response]) - ->getMock(); - - $this->controller->expects($this->any()) - ->method('dispatchEvent') - ->will($this->returnValue(new Event('test'))); - - $this->Request = $request; - $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', '_getProviderName', - '_mapUser', '_socialLogin', 'dispatchEvent', '_validateConfig', '_getController']); - - $this->SocialAuthenticate->expects($this->any()) - ->method('_getController') - ->will($this->returnValue($this->controller)); - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - public function tearDown() - { - unset($this->SocialAuthenticate, $this->controller); - } - - protected function _getSocialAuthenticateMock() - { - return $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') - ->disableOriginalConstructor() - ->getMock(); - } - - protected function _getSocialAuthenticateMockMethods($methods) - { - return $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') - ->disableOriginalConstructor() - ->setMethods($methods) - ->getMock(); - } - - /** - * test - * - * @expectedException \CakeDC\Users\Auth\Exception\MissingProviderConfigurationException - */ - public function testConstructorMissingConfig() - { - $socialAuthenticate = new SocialAuthenticate(new ComponentRegistry($this->controller)); - } - - /** - * test - * - */ - public function testConstructor() - { - $socialAuthenticate = new SocialAuthenticate(new ComponentRegistry($this->controller), [ - 'providers' => [ - 'facebook' => [ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.8', - 'redirectUri' => 'http://example.com/auth/facebook', - ] - ] - ] - ]); - - $this->assertInstanceOf('\CakeDC\Users\Auth\SocialAuthenticate', $socialAuthenticate); - } - - /** - * test - * - * @expectedException \CakeDC\Users\Auth\Exception\InvalidProviderException - */ - public function testConstructorMissingProvider() - { - $socialAuthenticate = new SocialAuthenticate(new ComponentRegistry($this->controller), [ - 'providers' => [ - 'facebook' => [ - 'className' => 'missing', - 'options' => [ - 'graphApiVersion' => 'v2.8', - 'redirectUri' => 'http://example.com/auth/facebook', - ] - ] - ] - ]); - } - - /** - * Test getUser - * - * @dataProvider providerGetUser - */ - public function testGetUserAuth($rawData, $mapper) - { - $user = $this->Table->get('00000000-0000-0000-0000-000000000002', ['contain' => ['SocialAccounts']]); - - $this->controller->expects($this->once()) - ->method('dispatchEvent') - ->with(UsersAuthComponent::EVENT_AFTER_REGISTER, compact('user')); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_authenticate') - ->with($this->Request) - ->will($this->returnValue($rawData)); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_getProviderName') - ->will($this->returnValue('facebook')); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_mapUser') - ->will($this->returnValue($mapper)); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_socialLogin') - ->will($this->returnValue($user)); - - $result = $this->SocialAuthenticate->getUser($this->Request); - $this->assertTrue($result['active']); - $this->assertEquals('00000000-0000-0000-0000-000000000002', $result['id']); - } - - /** - * Provider for getUser test method - * - */ - public function providerGetUser() - { - return [ - [ - 'rawData' => [ - 'token' => 'token', - 'id' => 'reference-2-1', - 'name' => 'User S', - 'first_name' => 'user', - 'last_name' => 'second', - 'email' => 'userSecond@example.com', - 'cover' => [ - 'id' => 'reference-2-1' - ], - 'gender' => 'female', - 'locale' => 'en_US', - 'link' => 'link', - ], - 'mappedData' => [ - 'id' => 'reference-2-1', - 'username' => null, - 'full_name' => 'User S', - 'first_name' => 'user', - 'last_name' => 'second', - 'email' => 'userSecond@example.com', - 'link' => 'link', - 'bio' => null, - 'locale' => 'en_US', - 'validated' => true, - 'credentials' => [ - 'token' => 'token', - 'secret' => null, - 'expires' => 1458423682 - ], - 'raw' => [ - - ], - 'provider' => 'Facebook' - ], - ] - - ]; - } - - /** - * Test getUser - * - */ - public function testGetUserSessionData() - { - $user = ['username' => 'username', 'email' => 'myemail@test.com']; - $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', - '_getProviderName', '_mapUser', '_touch', '_validateConfig']); - - $session = $this->getMockBuilder('Cake\Http\Session') - ->setMethods(['read', 'delete']) - ->getMock(); - $session->expects($this->once()) - ->method('read') - ->with('Users.social') - ->will($this->returnValue($user)); - - $session->expects($this->once()) - ->method('delete') - ->with('Users.social'); - - $this->Request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['getSession']) - ->getMock(); - $this->Request->expects($this->any()) - ->method('getSession') - ->will($this->returnValue($session)); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_touch') - ->will($this->returnValue($user)); - - $this->SocialAuthenticate->getUser($this->Request); - } - - /** - * Test getUser - * - * @dataProvider providerGetUser - */ - public function testGetUserNotEmailProvided($rawData, $mapper) - { - $this->SocialAuthenticate->expects($this->once()) - ->method('_authenticate') - ->with($this->Request) - ->will($this->returnValue($rawData)); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_getProviderName') - ->will($this->returnValue('facebook')); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_mapUser') - ->will($this->returnValue($mapper)); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_socialLogin') - ->will($this->throwException(new MissingEmailException('missing email'))); - - $this->controller->expects($this->once()) - ->method('dispatchEvent') - ->with(UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN); - - $this->controller->expects($this->once()) - ->method('failedSocialLogin'); - - $this->SocialAuthenticate->getUser($this->Request); - } - - /** - * Test getUser - * - * @dataProvider providerGetUser - */ - public function testGetUserNotActive($rawData, $mapper) - { - $this->SocialAuthenticate->expects($this->once()) - ->method('_authenticate') - ->with($this->Request) - ->will($this->returnValue($rawData)); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_getProviderName') - ->will($this->returnValue('facebook')); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_mapUser') - ->will($this->returnValue($mapper)); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_socialLogin') - ->will($this->throwException(new UserNotActiveException('user not active'))); - - $this->SocialAuthenticate->getUser($this->Request); - } - - /** - * Test getUser - * - * @dataProvider providerGetUser - */ - public function testGetUserNotActiveAccount($rawData, $mapper) - { - $this->SocialAuthenticate->expects($this->once()) - ->method('_authenticate') - ->with($this->Request) - ->will($this->returnValue($rawData)); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_getProviderName') - ->will($this->returnValue('facebook')); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_mapUser') - ->will($this->returnValue($mapper)); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_socialLogin') - ->will($this->throwException(new AccountNotActiveException('user not active'))); - - $this->SocialAuthenticate->getUser($this->Request); - } - - /** - * Test getUser - * - * @dataProvider providerTwitter - */ - public function testGetUserNotEmailProvidedTwitter($rawData, $mapper) - { - $this->SocialAuthenticate->expects($this->once()) - ->method('_authenticate') - ->with($this->Request) - ->will($this->returnValue($rawData)); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_getProviderName') - ->will($this->returnValue('twitter')); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_mapUser') - ->will($this->returnValue($mapper)); - - $this->SocialAuthenticate->expects($this->once()) - ->method('_socialLogin') - ->will($this->throwException(new MissingEmailException('missing email'))); - - $this->SocialAuthenticate->getUser($this->Request); - } - - /** - * Provider for getUser test method - * - */ - public function providerTwitter() - { - return [ - [ - 'rawData' => [ - 'token' => 'token', - 'id' => 'reference-2-1', - 'name' => 'User S', - 'first_name' => 'user', - 'last_name' => 'second', - 'email' => 'userSecond@example.com', - 'cover' => [ - 'id' => 'reference-2-1' - ], - 'gender' => 'female', - 'locale' => 'en_US', - 'link' => 'link', - ], - 'mappedData' => [ - 'id' => 'reference-2-1', - 'username' => null, - 'full_name' => 'User S', - 'first_name' => 'user', - 'last_name' => 'second', - 'email' => 'userSecond@example.com', - 'link' => 'link', - 'bio' => null, - 'locale' => 'en_US', - 'validated' => true, - 'credentials' => [ - 'token' => 'token', - 'secret' => null, - 'expires' => 1458423682 - ], - 'raw' => [ - - ], - 'provider' => 'Twitter' - ], - ] - - ]; - } - - /** - * Test _socialLogin - * - * @dataProvider providerMapper - */ - public function testSocialLogin() - { - $this->SocialAuthenticate = $this->_getSocialAuthenticateMock(); - - $reflectedClass = new ReflectionClass($this->SocialAuthenticate); - $socialLogin = $reflectedClass->getMethod('_socialLogin'); - $socialLogin->setAccessible(true); - $data = [ - 'id' => 'reference-2-1', - 'provider' => 'Facebook' - ]; - $result = $socialLogin->invoke($this->SocialAuthenticate, $data); - $this->assertEquals($result->id, '00000000-0000-0000-0000-000000000002'); - $this->assertTrue($result->active); - } - - /** - * Test _mapUser - * - * @dataProvider providerMapper - */ - public function testMapUser($data, $mappedData) - { - $data['token'] = $this->Token; - $this->SocialAuthenticate = $this->_getSocialAuthenticateMock(); - - $reflectedClass = new ReflectionClass($this->SocialAuthenticate); - $mapUser = $reflectedClass->getMethod('_mapUser'); - $mapUser->setAccessible(true); - - $this->Token->expects($this->once()) - ->method('getToken') - ->will($this->returnValue('token')); - - $this->Token->expects($this->once()) - ->method('getExpires') - ->will($this->returnValue(1458510952)); - - $result = $mapUser->invoke($this->SocialAuthenticate, 'Facebook', $data); - unset($result['raw']); - $this->assertEquals($mappedData, $result); - } - - /** - * Provider for _mapUser test method - * - */ - public function providerMapper() - { - return [ - [ - 'rawData' => [ - 'id' => 'my-facebook-id', - 'name' => 'My name.', - 'first_name' => 'My first name', - 'last_name' => 'My lastname.', - 'email' => 'myemail@example.com', - 'gender' => 'female', - 'locale' => 'en_US', - 'link' => 'https://www.facebook.com/app_scoped_user_id/my-facebook-id/', - ], - 'mappedData' => [ - 'id' => 'my-facebook-id', - 'username' => null, - 'full_name' => 'My name.', - 'first_name' => 'My first name', - 'last_name' => 'My lastname.', - 'email' => 'myemail@example.com', - 'avatar' => 'https://graph.facebook.com/my-facebook-id/picture?type=large', - 'gender' => 'female', - 'link' => 'https://www.facebook.com/app_scoped_user_id/my-facebook-id/', - 'bio' => null, - 'locale' => 'en_US', - 'validated' => true, - 'credentials' => [ - 'token' => 'token', - 'secret' => null, - 'expires' => (int)1458510952 - ], - 'provider' => 'Facebook' - ], - ] - - ]; - } - - /** - * Test _mapUser - * - * @expectedException CakeDC\Users\Exception\MissingProviderException - */ - public function testMapUserException() - { - $data = []; - $this->SocialAuthenticate = $this->_getSocialAuthenticateMock(); - - $reflectedClass = new ReflectionClass($this->SocialAuthenticate); - $mapUser = $reflectedClass->getMethod('_mapUser'); - $mapUser->setAccessible(true); - $mapUser->invoke($this->SocialAuthenticate, null, $data); - } - - /** - * Provider for normalizeConfig test method - * - * @dataProvider providers - */ - public function testNormalizeConfig($data, $oauth2, $callTimes, $enabledNoOAuth2Provider) - { - Configure::write('OAuth2', $oauth2); - $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', - '_getProviderName', '_mapUser', '_touch', '_validateConfig', '_normalizeConfig']); - - $this->SocialAuthenticate->expects($this->exactly($callTimes)) - ->method('_normalizeConfig'); - - $this->SocialAuthenticate->normalizeConfig($data, $enabledNoOAuth2Provider); - } - - /** - * Test normalizeConfig - * - * @expectedException CakeDC\Users\Auth\Exception\MissingProviderConfigurationException - */ - public function testNormalizeConfigException() - { - $this->SocialAuthenticate->normalizeConfig([]); - } - - /** - * Provider for normalizeConfig test method - * - */ - public function providers() - { - return [ - [ - [ - 'providers' => [ - 'facebook' => [ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - ], - 'instagram' => [ - 'className' => 'League\OAuth2\Client\Provider\Instagram', - ] - ], - - ], - [ - 'providers' => [ - 'facebook' => [ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - ], - 'instagram' => [ - 'className' => 'League\OAuth2\Client\Provider\Instagram', - ] - ] - ], - 2, - false - ], - [ - [ - 'providers' => [ - 'facebook' => [ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - ], - ], - - ], - [ - 'providers' => [ - 'facebook' => [ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - ], - ] - ], - 1, - false - ], - [ - [ - 'providers' => [ - 'facebook' => [ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - ], - ], - - ], - [ - 'providers' => [ - 'instagram' => [ - 'className' => 'League\OAuth2\Client\Provider\Instagram', - ] - ] - ], - 2, - false - ], - [ - [], - [], - 0, - true - ] - ]; - } -} diff --git a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php deleted file mode 100644 index 4c4908028..000000000 --- a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php +++ /dev/null @@ -1,44 +0,0 @@ -build(); - $this->assertInstanceOf(DefaultTwoFactorAuthenticationChecker::class, $result); - } - - /** - * Test getChecker method - * - * @return void - */ - public function testGetCheckerInvalidInterface() - { - Configure::write('GoogleAuthenticator.checker', 'stdClass'); - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage("Invalid config for 'GoogleAuthenticator.checker', 'stdClass' does not implement 'CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface'"); - $result = (new TwoFactorAuthenticationCheckerFactory())->build(); - } -} diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php deleted file mode 100644 index 367326745..000000000 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ /dev/null @@ -1,136 +0,0 @@ -backupUsersConfig = Configure::read('Users'); - - Router::reload(); - Router::connect('/route/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword' - ]); - Router::connect('/notAllowed/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'edit' - ]); - - Security::setSalt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); - Configure::write('App.namespace', 'Users'); - Configure::write('Users.GoogleAuthenticator.login', true); - - $this->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is', 'method']) - ->getMock(); - $this->request->expects($this->any())->method('is')->will($this->returnValue(true)); - $this->response = $this->getMockBuilder('Cake\Http\Response') - ->setMethods(['stop']) - ->getMock(); - $this->Controller = new Controller($this->request, $this->response); - $this->Registry = $this->Controller->components(); - $this->Controller->GoogleAuthenticator = new GoogleAuthenticatorComponent($this->Registry); - } - - /** - * tearDown method - * - * @return void - */ - public function tearDown() - { - parent::tearDown(); - - $_SESSION = []; - unset($this->Controller, $this->GoogleAuthenticator); - Configure::write('Users', $this->backupUsersConfig); - Configure::write('Users.GoogleAuthenticator.login', false); - } - - /** - * Test initialize - * - */ - public function testInitialize() - { - $this->Controller->GoogleAuthenticator = new GoogleAuthenticatorComponent($this->Registry); - $this->assertInstanceOf('CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent', $this->Controller->GoogleAuthenticator); - } - - /** - * test base64 qr-code returned from component - * @return void - */ - public function testgetQRCodeImageAsDataUri() - { - $this->Controller->GoogleAuthenticator->initialize([]); - $result = $this->Controller->GoogleAuthenticator->getQRCodeImageAsDataUri('test@localhost.com', '123123'); - - $this->assertContains('data:image/png;base64', $result); - } - - /** - * Making sure we return secret - * @return void - */ - public function testCreateSecret() - { - $this->Controller->GoogleAuthenticator->initialize([]); - $result = $this->Controller->GoogleAuthenticator->createSecret(); - $this->assertNotEmpty($result); - } - - /** - * Testing code verification in the component - * @return void - */ - public function testVerifyCode() - { - $this->Controller->GoogleAuthenticator->initialize([]); - $secret = $this->Controller->GoogleAuthenticator->createSecret(); - $verificationCode = $this->Controller->GoogleAuthenticator->tfa->getCode($secret); - - $verified = $this->Controller->GoogleAuthenticator->verifyCode($secret, $verificationCode); - $this->assertTrue($verified); - } -} diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php deleted file mode 100644 index e6b117686..000000000 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ /dev/null @@ -1,194 +0,0 @@ -request = new ServerRequest('controller_posts/index'); - $this->request = $this->request->withParam('pass', []); - $this->controller = $this->getMockBuilder('Cake\Controller\Controller') - ->setMethods(['redirect']) - ->setConstructorArgs([$this->request]) - ->getMock(); - $this->registry = new ComponentRegistry($this->controller); - $this->rememberMeComponent = new RememberMeComponent($this->registry, []); - } - - /** - * tearDown method - * - * @return void - */ - public function tearDown() - { - unset($this->rememberMeComponent); - - parent::tearDown(); - } - - /** - * Test initialize method - * - * @return void - */ - public function testInitialize() - { - $cookieOptions = [ - 'expires' => '1 month', - 'httpOnly' => true, - 'path' => '', - 'domain' => '', - 'secure' => false, - 'key' => '2a20bac195a9eb2e28f05b7ac7090afe599365a8fe480b7d8a5ce0f79687346e', - 'encryption' => 'aes', - 'enabled' => false - ]; - $this->assertEquals($cookieOptions, $this->rememberMeComponent->Cookie->configKey('remember_me')); - } - - /** - * Test initialize method - * - * @return void - */ - public function testInitializeException() - { - $salt = Security::getSalt(); - Security::setSalt('too small'); - try { - $this->rememberMeComponent = new RememberMeComponent($this->registry, []); - } catch (InvalidArgumentException $ex) { - $this->assertEquals('Invalid app salt, app salt must be at least 256 bits (32 bytes) long', $ex->getMessage()); - } - - Security::setSalt($salt); - } - - /** - * Test - * - * @return void - */ - public function testSetLoginCookie() - { - $event = new Event('event'); - $this->rememberMeComponent->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user']) - ->disableOriginalConstructor() - ->getMock(); - $this->rememberMeComponent->Auth->expects($this->once()) - ->method('user') - ->with('id') - ->will($this->returnValue(1)); - $this->rememberMeComponent->Cookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') - ->setMethods(['write']) - ->disableOriginalConstructor() - ->getMock(); - $this->rememberMeComponent->request = (new ServerRequest('/'))->withEnv('HTTP_USER_AGENT', 'user-agent') - ->withData(Configure::read('Users.Key.Data.rememberMe'), '1'); - $this->rememberMeComponent->Cookie->expects($this->once()) - ->method('write') - ->with('remember_me', ['id' => 1, 'user_agent' => 'user-agent']); - $this->rememberMeComponent->setLoginCookie($event); - } - - /** - * Test - * - * @return void - */ - public function testBeforeFilter() - { - $event = new Event('event'); - $this->rememberMeComponent->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) - ->disableOriginalConstructor() - ->getMock(); - $this->rememberMeComponent->Auth->expects($this->once()) - ->method('user'); - $user = ['id' => 1]; - $this->rememberMeComponent->Auth->expects($this->once()) - ->method('identify') - ->will($this->returnValue($user)); - $this->rememberMeComponent->Auth->expects($this->once()) - ->method('setUser') - ->with($user); - $this->controller->expects($this->once()) - ->method('redirect') - ->with('/controller_posts/index'); - $this->rememberMeComponent->beforeFilter($event); - } - - /** - * Test - * - * @return void - */ - public function testBeforeFilterNotIdentified() - { - $event = new Event('event'); - $this->rememberMeComponent->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) - ->disableOriginalConstructor() - ->getMock(); - $this->rememberMeComponent->Auth->expects($this->at(0)) - ->method('user'); - $this->rememberMeComponent->Auth->expects($this->at(1)) - ->method('identify'); - - $this->assertNull($this->rememberMeComponent->beforeFilter($event)); - } - - /** - * Test - * - * @return void - */ - public function testBeforeFilterUserLoggedIn() - { - $event = new Event('event'); - $this->rememberMeComponent->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) - ->disableOriginalConstructor() - ->getMock(); - $this->rememberMeComponent->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue([ - 'id' => 1, - ])); - $this->assertNull($this->rememberMeComponent->beforeFilter($event)); - } -} diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php deleted file mode 100644 index 7860d3439..000000000 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ /dev/null @@ -1,515 +0,0 @@ -backupUsersConfig = Configure::read('Users'); - - Router::reload(); - Router::connect('/route/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword' - ]); - Router::connect('/notAllowed/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'edit' - ]); - Security::setSalt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); - Configure::write('App.namespace', 'Users'); - $this->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is', 'method']) - ->getMock(); - $this->request->expects($this->any())->method('is')->will($this->returnValue(true)); - $this->response = $this->getMockBuilder('Cake\Http\Response') - ->setMethods(['stop']) - ->getMock(); - $this->Controller = new Controller($this->request, $this->response); - $this->Controller->setName('Users'); - $this->Registry = $this->Controller->components(); - $this->Controller->UsersAuth = new UsersAuthComponent($this->Registry); - } - - /** - * tearDown method - * - * @return void - */ - public function tearDown() - { - parent::tearDown(); - - $_SESSION = []; - unset($this->Controller, $this->UsersAuth); - Configure::write('Users', $this->backupUsersConfig); - } - - /** - * Test initialize - * - */ - public function testInitialize() - { - $this->Registry->unload('Auth'); - $this->Controller->UsersAuth = new UsersAuthComponent($this->Registry); - $this->assertInstanceOf('CakeDC\Users\Controller\Component\UsersAuthComponent', $this->Controller->UsersAuth); - } - - /** - * Test initialize with not rememberMe component needed - * - */ - public function testInitializeNoRequiredRememberMe() - { - Configure::write('Users.RememberMe.active', false); - $class = 'CakeDC\Users\Controller\Component\UsersAuthComponent'; - $this->Controller->UsersAuth = $this->getMockBuilder($class) - ->setMethods(['_loadRememberMe', '_initAuth', '_loadSocialLogin', '_attachPermissionChecker']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->UsersAuth->expects($this->once()) - ->method('_initAuth'); - $this->Controller->UsersAuth->expects($this->never()) - ->method('_loadRememberMe'); - $this->Controller->UsersAuth->initialize([]); - } - - /** - * test - * - * @return void - */ - public function testIsUrlAuthorizedUserNotLoggedIn() - { - $event = new Event('event'); - $event->setData([ - 'url' => '/route', - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(false)); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertFalse($result); - } - - /** - * test The user is not logged in, but the controller action is public $this->Auth->allow() - * - * @return void - */ - public function testIsUrlAuthorizedUserNotLoggedInActionAllowed() - { - $event = new Event('event'); - $event->setData([ - 'url' => '/route', - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->allowedActions = ['requestResetPassword']; - $this->Controller->Auth->expects($this->never()) - ->method('user'); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertTrue($result); - } - - /** - * test The user is logged in and not allowed by rules to access this action, - * but the controller action is public $this->Auth->allow() - * - * @return void - */ - public function testIsUrlAuthorizedUserLoggedInNotAllowedActionAllowed() - { - $event = new Event('event'); - $event->setData([ - 'url' => '/notAllowed', - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->allowedActions = ['edit']; - $this->Controller->Auth->expects($this->never()) - ->method('user'); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertTrue($result); - } - - /** - * test The user is logged in and allowed by rules to access this action, - * and the controller action is public $this->Auth->allow() - * - * @return void - */ - public function testIsUrlAuthorizedUserLoggedInAllowedActionAllowed() - { - $event = new Event('event'); - $event->setData([ - 'url' => '/route', - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->allowedActions = ['requestResetPassword']; - $this->Controller->Auth->expects($this->never()) - ->method('user'); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertTrue($result); - } - - /** - * test - * - * @return void - */ - public function testIsUrlAuthorizedNoUrl() - { - $event = new Event('event'); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertFalse($result); - } - - /** - * test - * - * @return void - */ - public function testIsUrlAuthorizedUrlRelativeString() - { - $event = new Event('event'); - $event->setData([ - 'url' => '/route', - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(['id' => 1])); - $this->Controller->Auth->expects($this->once()) - ->method('isAuthorized') - ->with(null, $this->callback(function ($subject) { - return $subject->getAttribute('params') === [ - 'pass' => [], - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - '_matchedRoute' => '/route/*', - ]; - })) - ->will($this->returnValue(true)); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertTrue($result); - } - - /** - * test - * - * @return void - * @expectedException \Cake\Routing\Exception\MissingRouteException - */ - public function testIsUrlAuthorizedMissingRouteString() - { - $event = new Event('event'); - $event->setData([ - 'url' => '/missingRoute', - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->expects($this->never()) - ->method('user'); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - } - - /** - * test - * - * @return void - * @expectedException \Cake\Routing\Exception\MissingRouteException - */ - public function testIsUrlAuthorizedMissingRouteArray() - { - $event = new Event('event'); - $event->setData([ - 'url' => [ - 'controller' => 'missing', - 'action' => 'missing', - ], - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->expects($this->never()) - ->method('user'); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - } - - /** - * test - * - * @return void - */ - public function testIsUrlAuthorizedUrlAbsoluteForCurrentAppString() - { - $event = new Event('event'); - $event->setData([ - 'url' => Router::fullBaseUrl() . '/route', - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(['id' => 1])); - $this->Controller->Auth->expects($this->once()) - ->method('isAuthorized') - ->with(null, $this->callback(function ($subject) { - return $subject->getAttribute('params') === [ - 'pass' => [], - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - '_matchedRoute' => '/route/*', - ]; - })) - ->will($this->returnValue(true)); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertTrue($result); - } - - /** - * test - * - * @return void - */ - public function testIsUrlAuthorizedUrlRelativeForCurrentAppString() - { - $event = new Event('event'); - $event->setData([ - 'url' => 'route', - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(['id' => 1])); - $this->Controller->Auth->expects($this->once()) - ->method('isAuthorized') - ->with(null, $this->callback(function ($subject) { - return $subject->getAttribute('params') === [ - 'pass' => [], - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - '_matchedRoute' => '/route/*', - ]; - })) - ->will($this->returnValue(true)); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertTrue($result); - } - - /** - * - * - * @return void - */ - public function testIsUrlAuthorizedUrlAbsoluteForOtherAppString() - { - $event = new Event('event'); - $event->setData([ - 'url' => 'http://example.com', - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->expects($this->never()) - ->method('user'); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertTrue($result); - } - - /** - * test - * - * @return void - */ - public function testIsUrlAuthorizedUrlArray() - { - $event = new Event('event'); - $event->setData([ - 'url' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - 'pass-one' - ], - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(['id' => 1])); - $this->Controller->Auth->expects($this->once()) - ->method('isAuthorized') - ->with(null, $this->callback(function ($subject) { - return $subject->getAttribute('params') === [ - 'pass' => ['pass-one'], - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - '_matchedRoute' => '/route/*', - ]; - })) - ->will($this->returnValue(true)); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertTrue($result); - } - - /** - * When application is installed using a base folder, we need to ensure array routes are - * normalized too to remove the base from the url used for matching the rules - * - * @see https://github.com/CakeDC/users/issues/538 - * - * @return void - */ - public function testIsUrlAuthorizedBaseUrl() - { - Configure::write('App.base', 'app'); - Router::pushRequest(new ServerRequest([ - 'base' => '/app', - 'url' => '/', - ])); - $event = new Event('event'); - $event->setData([ - 'url' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - ], - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(['id' => 1])); - $this->Controller->Auth->expects($this->once()) - ->method('isAuthorized') - ->with(null, $this->callback(function ($subject) { - return $subject->getAttribute('params') === [ - 'pass' => [], - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'requestResetPassword', - '_matchedRoute' => '/route/*', - ]; - })) - ->will($this->returnValue(true)); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertTrue($result); - } - /** - * test The user is logged in and allowed by rules to access this action, - * and we are checking another controller action not allowed - * - * this case would prevent permissions checked for allowed actions in another controller - * @see https://github.com/CakeDC/users/issues/527 for a workaround if you need to - * check allowed on another controller - * - * @return void - */ - public function testIsUrlAuthorizedUserLoggedInAllowedActionAllowedAnotherController() - { - Router::connect('/route-another-controller/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'AnotherController', - 'action' => 'requestResetPassword' - ]); - $event = new Event('event'); - $event->setData([ - 'url' => '/route-another-controller', - ]); - $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'isAuthorized']) - ->disableOriginalConstructor() - ->getMock(); - $this->Controller->Auth->allowedActions = ['requestResetPassword']; - $this->Controller->Auth->expects($this->once()) - ->method('user') - ->will($this->returnValue(false)); - $result = $this->Controller->UsersAuth->isUrlAuthorized($event); - $this->assertFalse($result); - } -} diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php deleted file mode 100644 index 296f15f2f..000000000 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ /dev/null @@ -1,204 +0,0 @@ -configOpauth = Configure::read('Opauth'); - $this->configRememberMe = Configure::read('Users.RememberMe.active'); - Configure::write('Opauth', null); - Configure::write('Users.RememberMe.active', false); - - Email::setConfigTransport('test', [ - 'className' => 'Debug' - ]); - $this->configEmail = Email::getConfig('default'); - Email::drop('default'); - Email::setConfig('default', [ - 'transport' => 'test', - 'from' => 'cakedc@example.com' - ]); - - $request = new ServerRequest('/users/users/index'); - $request = $request->withParam('plugin', 'CakeDC/Users'); - - $this->Controller = $this->getMockBuilder('CakeDC\Users\Controller\SocialAccountsController') - ->setMethods(['redirect', 'render']) - ->setConstructorArgs([$request, null, 'SocialAccounts']) - ->getMock(); - $this->Controller->SocialAccounts = $this->getMockForModel('CakeDC\Users.SocialAccounts', ['sendSocialValidationEmail'], [ - 'className' => 'CakeDC\Users\Model\Table\SocialAccountsTable' - ]); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - Email::drop('default'); - Email::dropTransport('test'); - //Email::setConfig('default', $this->configEmail); - - Configure::write('Opauth', $this->configOpauth); - Configure::write('Users.RememberMe.active', $this->configRememberMe); - - parent::tearDown(); - } - - /** - * test - * - * @return void - */ - public function testValidateAccountHappy() - { - $this->Controller->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - $this->Controller->validateAccount('Facebook', 'reference-1-1234', 'token-1234'); - $this->assertEquals('Account validated successfully', $this->Controller->request->getSession()->read('Flash.flash.0.message')); - } - - /** - * test - * - * @return void - */ - public function testValidateAccountInvalidToken() - { - $this->Controller->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - $this->Controller->validateAccount('Facebook', 'reference-1-1234', 'token-not-found'); - $this->assertEquals('Invalid token and/or social account', $this->Controller->request->getSession()->read('Flash.flash.0.message')); - } - - /** - * test - * - * @return void - */ - public function testValidateAccountAlreadyActive() - { - $this->Controller->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); - $this->assertEquals('Social Account already active', $this->Controller->request->getSession()->read('Flash.flash.0.message')); - } - - /** - * test - * - * @return void - */ - public function testResendValidationHappy() - { - $behaviorMock = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialAccountBehavior') - ->setMethods(['sendSocialValidationEmail']) - ->setConstructorArgs([$this->Controller->SocialAccounts]) - ->getMock(); - $this->Controller->SocialAccounts->behaviors()->set('SocialAccount', $behaviorMock); - $behaviorMock->expects($this->once()) - ->method('sendSocialValidationEmail') - ->will($this->returnValue(true)); - $this->Controller->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - - $this->Controller->resendValidation('Facebook', 'reference-1-1234'); - $this->assertEquals('Email sent successfully', $this->Controller->request->getSession()->read('Flash.flash.0.message')); - } - - /** - * test - * - * @return void - */ - public function testResendValidationEmailError() - { - $behaviorMock = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialAccountBehavior') - ->setMethods(['sendSocialValidationEmail']) - ->setConstructorArgs([$this->Controller->SocialAccounts]) - ->getMock(); - $this->Controller->SocialAccounts->behaviors()->set('SocialAccount', $behaviorMock); - $behaviorMock->expects($this->once()) - ->method('sendSocialValidationEmail') - ->will($this->returnValue(false)); - $this->Controller->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - - $this->Controller->resendValidation('Facebook', 'reference-1-1234'); - $this->assertEquals('Email could not be sent', $this->Controller->request->getSession()->read('Flash.flash.0.message')); - } - - /** - * test - * - * @return void - */ - public function testResendValidationInvalid() - { - $this->Controller->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - $this->Controller->resendValidation('Facebook', 'reference-invalid'); - $this->assertEquals('Invalid account', $this->Controller->request->getSession()->read('Flash.flash.0.message')); - } - - /** - * test - * - * @return void - */ - public function testResendValidationAlreadyActive() - { - $this->Controller->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); - $this->assertEquals('Social Account already active', $this->Controller->request->getSession()->read('Flash.flash.0.message')); - } -} diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php deleted file mode 100644 index 6cc88cc19..000000000 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ /dev/null @@ -1,220 +0,0 @@ -traitMockMethods)); - $this->table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - try { - $this->Trait = $this->getMockBuilder($this->traitClassName) - ->setMethods($traitMockMethods) - ->getMockForTrait(); - $this->Trait->expects($this->any()) - ->method('getUsersTable') - ->will($this->returnValue($this->table)); - } catch (PHPUnit_Framework_MockObject_RuntimeException $ex) { - debug($ex); - $this->fail("Unit tests extending BaseTraitTest should declare the trait class name in the \$traitClassName variable before calling setUp()"); - } - - if ($this->mockDefaultEmail) { - Email::setConfigTransport('test', [ - 'className' => 'Debug' - ]); - $this->configEmail = Email::getConfig('default'); - Email::drop('default'); - Email::setConfig('default', [ - 'transport' => 'test', - 'from' => 'cakedc@example.com' - ]); - } - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - unset($this->table, $this->Trait); - if ($this->mockDefaultEmail) { - Email::drop('default'); - Email::dropTransport('test'); - //Email::setConfig('default', $this->setConfigEmail); - } - parent::tearDown(); - } - - /** - * Mock session and mock session attributes - * - * @return void - */ - protected function _mockSession($attributes) - { - $session = new \Cake\Http\Session(); - - foreach ($attributes as $field => $value) { - $session->write($field, $value); - } - - $this->Trait->request - ->expects($this->any()) - ->method('session') - ->willReturn($session); - } - - /** - * mock request for GET - * - * @return void - */ - protected function _mockRequestGet($withSession = false) - { - $methods = ['is', 'referer', 'getData']; - - if ($withSession) { - $methods[] = 'session'; - } - - $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') - ->setMethods($methods) - ->getMock(); - $this->Trait->request->expects($this->any()) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); - } - - /** - * mock Flash Component - * - * @return void - */ - protected function _mockFlash() - { - $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['error', 'success']) - ->disableOriginalConstructor() - ->getMock(); - } - - /** - * mock Request for POST, is and allow methods - * - * @param mixed $with used in with - * @return void - */ - protected function _mockRequestPost($with = 'post') - { - $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') - ->setMethods(['is', 'getData', 'allow']) - ->getMock(); - $this->Trait->request->expects($this->any()) - ->method('is') - ->with($with) - ->will($this->returnValue(true)); - } - - /** - * Mock Auth and retur user id 1 - * - * @return void - */ - protected function _mockAuthLoggedIn($user = []) - { - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) - ->disableOriginalConstructor() - ->getMock(); - $user += [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'password' => '12345', - ]; - $this->Trait->Auth->expects($this->any()) - ->method('identify') - ->will($this->returnValue($user)); - $this->Trait->Auth->expects($this->any()) - ->method('user') - ->with('id') - ->will($this->returnValue($user['id'])); - } - - /** - * Mock the Auth component - * - * @return void - */ - protected function _mockAuth() - { - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) - ->disableOriginalConstructor() - ->getMock(); - } - - /** - * mock utility - * - * @param Event $event event - * @param array $result array of data - * @return void - */ - protected function _mockDispatchEvent(Event $event = null, $result = []) - { - if (is_null($event)) { - $event = new Event('cool-name-here'); - } - - if (!empty($result)) { - $event->result = new Entity($result); - } - $this->Trait->expects($this->any()) - ->method('dispatchEvent') - ->will($this->returnValue($event)); - } -} diff --git a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php deleted file mode 100644 index 3511fd9a5..000000000 --- a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php +++ /dev/null @@ -1,41 +0,0 @@ -controller = $this->getMockBuilder('Cake\Controller\Controller') - ->setMethods(['header', 'redirect', 'render', '_stop']) - ->getMock(); - $this->controller->Trait = $this->getMockForTrait('CakeDC\Users\Controller\Traits\CustomUsersTableTrait'); - } - - public function tearDown() - { - parent::tearDown(); - } - - public function testGetUsersTable() - { - $table = $this->controller->Trait->getUsersTable(); - $this->assertEquals('CakeDC/Users.Users', $table->getRegistryAlias()); - $newTable = new Table(); - $this->controller->Trait->setUsersTable($newTable); - $this->assertSame($newTable, $this->controller->Trait->getUsersTable()); - } -} diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php deleted file mode 100644 index 00ce7b11b..000000000 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ /dev/null @@ -1,825 +0,0 @@ -oauthConfig === null) { - $this->oauthConfig = Configure::read('OAuth'); - } - $this->traitClassName = 'CakeDC\Users\Controller\Traits\LinkSocialTrait'; - $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; - - parent::setUp(); - $request = new ServerRequest(); - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set']) - ->getMockForTrait(); - - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setConfig']) - ->disableOriginalConstructor() - ->getMock(); - - $this->Trait->request = $request; - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - Configure::write('OAuth', $this->oauthConfig); - parent::tearDown(); - } - - /** - * mock request for GET - * - * @return void - */ - protected function _mockRequestGet($withSession = false) - { - $methods = ['is', 'referer', 'getData', 'getQuery', 'getQueryParams']; - - if ($withSession) { - $methods[] = 'session'; - } - - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods($methods) - ->getMock(); - $this->Trait->request->expects($this->any()) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); - } - - /** - * test linkSocial method - * - * @return void - */ - public function testLinkSocialHappy() - { - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) - ->getMockForTrait(); - - $this->_mockRequestGet(true); - $this->_mockAuthLoggedIn(); - $this->_mockDispatchEvent(new Event('event')); - $this->_mockFlash(); - $this->_mockSession([]); - $this->Trait->Flash->expects($this->never()) - ->method('error'); - - $this->Trait->Flash->expects($this->never()) - ->method('success'); - - $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') - ->setMethods(['getAuthorizationUrl', 'getState']) - ->disableOriginalConstructor() - ->getMock(); - - $ProviderMock->expects($this->once()) - ->method('getAuthorizationUrl') - ->will($this->returnValue('http://localhost/fake/facebook/login')); - - $ProviderMock->expects($this->once()) - ->method('getState') - ->will($this->returnValue('a3423ja9ads90u3242309')); - - $this->Trait->expects($this->once()) - ->method('_createSocialProvider') - ->with( - $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => 'testclientidtestclientid', - 'clientSecret' => 'testclientsecrettestclientsecret' - ] - ]) - ) - ->will($this->returnValue($ProviderMock)); - - $this->Trait->expects($this->once()) - ->method('redirect') - ->with( - $this->equalTo('http://localhost/fake/facebook/login') - ); - - $this->Trait->linkSocial('facebook'); - } - - /** - * test - * - * @return void - */ - public function testLinkSocialNotDefineLinkSocialRedirectUri() - { - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - Configure::delete('OAuth.providers.facebook.options.callbackLinkSocialUri'); - - $result = false; - try { - $this->_mockRequestGet(); - $this->_mockAuthLoggedIn(); - $this->_mockFlash(); - - $this->_mockDispatchEvent(new Event('event')); - - $this->Trait->linkSocial('facebook'); - } catch (NotFoundException $e) { - $result = true; - } - $this->assertTrue($result); - } - - /** - * test - * - * @return void - */ - public function testLinkSocialNotDefinedClientId() - { - Configure::delete('OAuth.providers.facebook.options.clientId'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - $result = false; - try { - $this->_mockRequestGet(); - $this->_mockAuthLoggedIn(); - $this->_mockFlash(); - - $this->_mockDispatchEvent(new Event('event')); - - $this->Trait->linkSocial('facebook'); - } catch (NotFoundException $e) { - $result = true; - } - $this->assertTrue($result); - } - - /** - * test - * - * @return void - */ - public function testLinkSocialNotDefinedClientSecret() - { - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::delete('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - $result = false; - try { - $this->_mockRequestGet(); - $this->_mockAuthLoggedIn(); - $this->_mockFlash(); - - $this->_mockDispatchEvent(new Event('event')); - - $this->Trait->linkSocial('facebook'); - } catch (NotFoundException $e) { - $result = true; - } - $this->assertTrue($result); - } - - /** - * test - * - * @return void - */ - public function testCallbackLinkSocialHappy() - { - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) - ->getMockForTrait(); - - $this->Trait->expects($this->any()) - ->method('getUsersTable') - ->will($this->returnValue($Table)); - - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setConfig']) - ->disableOriginalConstructor() - ->getMock(); - - $this->_mockRequestGet(true); - $this->Trait->request->expects($this->once()) - ->method('getQuery') - ->with('code') - ->will($this->returnValue('99999000222220')); - - $this->Trait->request->expects($this->once()) - ->method('getQueryParams') - ->will($this->returnValue([ - 'code' => '99999000222220', - 'state' => 'a393j2942789' - ])); - - $this->_mockSession([ - 'SocialLink' => [ - 'oauth2state' => 'a393j2942789' - ] - ]); - $this->_mockAuthLoggedIn(); - $this->_mockDispatchEvent(new Event('event')); - $this->_mockFlash(); - $this->Trait->Flash->expects($this->never()) - ->method('error'); - - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with(__d('CakeDC/Users', 'Social account was associated.')); - - $fbToken = new AccessToken([ - 'access_token' => 'token', - 'tokenSecret' => null, - 'expires' => 1458423682 - ]); - $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') - ->setMethods(['getAccessToken', 'getResourceOwner']) - ->disableOriginalConstructor() - ->getMock(); - - $ProviderMock->expects($this->once()) - ->method('getAccessToken') - ->with( - $this->equalTo('authorization_code'), - $this->equalTo([ - 'code' => '99999000222220' - ]) - )->will($this->returnValue($fbToken)); - - $fbUser = new FacebookUser([ - 'id' => '9999911112255', - 'name' => 'Ful Name.', - 'username' => 'mock_username', - 'first_name' => 'First Name', - 'last_name' => 'Last name', - 'email' => 'user-1@test.com', - 'Location' => 'mock_home', - 'bio' => 'mock_description', - 'link' => 'facebook-link-15579', - ]); - $ProviderMock->expects($this->once()) - ->method('getResourceOwner') - ->with( - $this->equalTo($fbToken) - )->will($this->returnValue($fbUser)); - - $this->Trait->expects($this->once()) - ->method('_createSocialProvider') - ->with( - $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => 'testclientidtestclientid', - 'clientSecret' => 'testclientsecrettestclientsecret' - ] - ]) - ) - ->will($this->returnValue($ProviderMock)); - - $this->Trait->callbackLinkSocial('facebook'); - - $actual = $Table->SocialAccounts->find('all')->where(['reference' => '9999911112255'])->firstOrFail(); - - $expiresTime = new Time(); - $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); - - $expected = [ - 'provider' => 'Facebook', - 'username' => 'mock_username', - 'reference' => '9999911112255', - 'avatar' => 'https://graph.facebook.com/9999911112255/picture?type=large', - 'description' => 'mock_description', - 'token' => 'token', - 'token_secret' => null, - 'user_id' => '00000000-0000-0000-0000-000000000001', - 'active' => true - ]; - foreach ($expected as $property => $value) { - $check = $actual->$property; - $this->assertEquals($value, $actual->$property); - } - $this->assertEquals($tokenExpires, $actual->token_expires->format('Y-m-d H:i:s')); - } - - /** - * test - * - * @return void - */ - public function testCallbackLinkSocialWithValidationErrors() - { - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - $user = TableRegistry::getTableLocator()->get('CakeDC/Users.Users')->get('00000000-0000-0000-0000-000000000001'); - $user->setErrors([ - 'social_accounts' => [ - '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') - ] - ]); - $Table = $this->getMockForModel('CakeDC/Users.Users', ['linkSocialAccount', 'get']); - $Table->setAlias('Users'); - - $Table->expects($this->once()) - ->method('get') - ->will($this->returnValue($user)); - - $Table->expects($this->once()) - ->method('linkSocialAccount') - ->will($this->returnValue($user)); - - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) - ->getMockForTrait(); - - $this->Trait->expects($this->any()) - ->method('getUsersTable') - ->will($this->returnValue($Table)); - - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setConfig']) - ->disableOriginalConstructor() - ->getMock(); - - $this->_mockRequestGet(true); - $this->Trait->request->expects($this->once()) - ->method('getQuery') - ->with('code') - ->will($this->returnValue('99999000222220')); - - $this->Trait->request->expects($this->once()) - ->method('getQueryParams') - ->will($this->returnValue([ - 'code' => '99999000222220', - 'state' => 'a393j2942789' - ])); - - $this->_mockSession([ - 'SocialLink' => [ - 'oauth2state' => 'a393j2942789' - ] - ]); - $this->_mockAuthLoggedIn(); - $this->_mockDispatchEvent(new Event('event')); - $this->_mockFlash(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); - - $this->Trait->Flash->expects($this->never()) - ->method('success'); - - $fbToken = new AccessToken([ - 'access_token' => 'token', - 'tokenSecret' => null, - 'expires' => 1458423682 - ]); - $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') - ->setMethods(['getAccessToken', 'getResourceOwner']) - ->disableOriginalConstructor() - ->getMock(); - - $ProviderMock->expects($this->once()) - ->method('getAccessToken') - ->with( - $this->equalTo('authorization_code'), - $this->equalTo([ - 'code' => '99999000222220' - ]) - )->will($this->returnValue($fbToken)); - - $fbUser = new FacebookUser([ - 'id' => '9999911112255', - 'name' => 'Ful Name.', - 'username' => 'mock_username', - 'first_name' => 'First Name', - 'last_name' => 'Last name', - 'email' => 'user-1@test.com', - 'Location' => 'mock_home', - 'bio' => 'mock_description', - 'link' => 'facebook-link-15579', - ]); - $ProviderMock->expects($this->once()) - ->method('getResourceOwner') - ->with( - $this->equalTo($fbToken) - )->will($this->returnValue($fbUser)); - - $this->Trait->expects($this->once()) - ->method('_createSocialProvider') - ->with( - $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => 'testclientidtestclientid', - 'clientSecret' => 'testclientsecrettestclientsecret' - ] - ]) - ) - ->will($this->returnValue($ProviderMock)); - - $this->Trait->callbackLinkSocial('facebook'); - - $actual = $Table->SocialAccounts->exists(['reference' => '9999911112255']); - $this->assertFalse($actual); - } - - /** - * test - * - * @return void - */ - public function testCallbackLinkSocialFailGettingAccessToken() - { - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) - ->getMockForTrait(); - - $this->Trait->expects($this->any()) - ->method('getUsersTable') - ->will($this->returnValue($Table)); - - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setConfig']) - ->disableOriginalConstructor() - ->getMock(); - - $this->_mockRequestGet(true); - $this->Trait->request->expects($this->once()) - ->method('getQuery') - ->with('code') - ->will($this->returnValue('99999000222220')); - - $this->Trait->request->expects($this->once()) - ->method('getQueryParams') - ->will($this->returnValue([ - 'code' => '99999000222220', - 'state' => 'a393j2942789' - ])); - - $this->_mockSession([ - 'SocialLink' => [ - 'oauth2state' => 'a393j2942789' - ] - ]); - $this->_mockAuthLoggedIn(); - $this->_mockDispatchEvent(new Event('event')); - $this->_mockFlash(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); - - $this->Trait->Flash->expects($this->never()) - ->method('success'); - - $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') - ->setMethods(['getAccessToken', 'getResourceOwner']) - ->disableOriginalConstructor() - ->getMock(); - - $ProviderMock->expects($this->once()) - ->method('getAccessToken') - ->with( - $this->equalTo('authorization_code'), - $this->equalTo([ - 'code' => '99999000222220' - ]) - )->will($this->throwException(new \Exception)); - - $ProviderMock->expects($this->never()) - ->method('getResourceOwner'); - - $this->Trait->expects($this->once()) - ->method('_createSocialProvider') - ->with( - $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => 'testclientidtestclientid', - 'clientSecret' => 'testclientsecrettestclientsecret' - ] - ]) - ) - ->will($this->returnValue($ProviderMock)); - - $this->Trait->callbackLinkSocial('facebook'); - - $actual = $Table->SocialAccounts->exists(['reference' => '9999911112255']); - $this->assertFalse($actual); - } - - /** - * test - * - * @return void - */ - public function testCallbackLinkSocialQueryHasErrors() - { - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) - ->getMockForTrait(); - - $this->Trait->expects($this->any()) - ->method('getUsersTable') - ->will($this->returnValue($Table)); - - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setConfig']) - ->disableOriginalConstructor() - ->getMock(); - - $this->_mockRequestGet(true); - $this->Trait->request->expects($this->never()) - ->method('getQuery'); - - $this->Trait->request->expects($this->once()) - ->method('getQueryParams') - ->will($this->returnValue([ - 'error' => 'We got some error', - 'code' => '99999000222220', - 'state' => 'a393j2942789' - ])); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with( - $this->equalTo(['action' => 'profile']) - ); - - $this->_mockSession([ - 'SocialLink' => [ - 'oauth2state' => 'a393j2942789' - ] - ]); - $this->_mockAuthLoggedIn(); - $this->_mockDispatchEvent(new Event('event')); - $this->_mockFlash(); - $this->Trait->Flash->expects($this->never()) - ->method('success'); - - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); - - $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') - ->setMethods(['getAccessToken', 'getResourceOwner']) - ->disableOriginalConstructor() - ->getMock(); - - $ProviderMock->expects($this->never()) - ->method('getAccessToken'); - - $ProviderMock->expects($this->never()) - ->method('getResourceOwner'); - - $this->Trait->expects($this->once()) - ->method('_createSocialProvider') - ->with( - $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => 'testclientidtestclientid', - 'clientSecret' => 'testclientsecrettestclientsecret' - ] - ]) - ) - ->will($this->returnValue($ProviderMock)); - - $this->Trait->callbackLinkSocial('facebook'); - } - - /** - * test - * - * @return void - */ - public function testCallbackLinkSocialWrongState() - { - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) - ->getMockForTrait(); - - $this->Trait->expects($this->any()) - ->method('getUsersTable') - ->will($this->returnValue($Table)); - - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setConfig']) - ->disableOriginalConstructor() - ->getMock(); - - $this->_mockRequestGet(true); - $this->Trait->request->expects($this->never()) - ->method('getQuery'); - - $this->Trait->request->expects($this->once()) - ->method('getQueryParams') - ->will($this->returnValue([ - 'code' => '99999000222220', - 'state' => 'bd393j2942789' - ])); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with( - $this->equalTo(['action' => 'profile']) - ); - - $this->_mockSession([ - 'SocialLink' => [ - 'oauth2state' => 'a393j2942789' - ] - ]); - $this->_mockAuthLoggedIn(); - $this->_mockDispatchEvent(new Event('event')); - $this->_mockFlash(); - $this->Trait->Flash->expects($this->never()) - ->method('success'); - - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); - - $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') - ->setMethods(['getAccessToken', 'getResourceOwner']) - ->disableOriginalConstructor() - ->getMock(); - - $ProviderMock->expects($this->never()) - ->method('getAccessToken'); - - $ProviderMock->expects($this->never()) - ->method('getResourceOwner'); - - $this->Trait->expects($this->once()) - ->method('_createSocialProvider') - ->with( - $this->equalTo([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => 'testclientidtestclientid', - 'clientSecret' => 'testclientsecrettestclientsecret' - ] - ]) - ) - ->will($this->returnValue($ProviderMock)); - - $this->Trait->callbackLinkSocial('facebook'); - } - - /** - * test - * - * @return void - */ - public function testCallbackLinkSocialMissingCode() - { - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set', 'getUsersTable', 'log']) - ->getMockForTrait(); - - $this->Trait->expects($this->any()) - ->method('getUsersTable') - ->will($this->returnValue($Table)); - - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setConfig']) - ->disableOriginalConstructor() - ->getMock(); - - $this->_mockRequestGet(true); - $this->Trait->request->expects($this->never()) - ->method('getQuery'); - - $this->Trait->request->expects($this->once()) - ->method('getQueryParams') - ->will($this->returnValue([ - 'state' => 'bd393j2942789' - ])); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with( - $this->equalTo(['action' => 'profile']) - ); - - $this->_mockSession([ - 'SocialLink' => [ - 'oauth2state' => 'a393j2942789' - ] - ]); - $this->_mockAuthLoggedIn(); - $this->_mockDispatchEvent(new Event('event')); - $this->_mockFlash(); - $this->Trait->Flash->expects($this->never()) - ->method('success'); - - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); - - $this->Trait->callbackLinkSocial('facebook'); - } -} diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php deleted file mode 100644 index a897f0f50..000000000 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ /dev/null @@ -1,813 +0,0 @@ -traitClassName = 'CakeDC\Users\Controller\Traits\LoginTrait'; - $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; - - parent::setUp(); - $request = new ServerRequest(); - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set']) - ->getMockForTrait(); - - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setConfig']) - ->disableOriginalConstructor() - ->getMock(); - - $this->Trait->request = $request; - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - parent::tearDown(); - } - - /** - * test - * - * @return void - */ - public function testLoginHappy() - { - $this->_mockDispatchEvent(new Event('event')); - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is']) - ->getMock(); - $this->Trait->request->expects($this->any()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) - ->disableOriginalConstructor() - ->getMock(); - $user = [ - 'id' => 1, - ]; - $redirectLoginOK = '/'; - $this->Trait->Auth->expects($this->at(0)) - ->method('identify') - ->will($this->returnValue($user)); - $this->Trait->Auth->expects($this->at(1)) - ->method('setUser') - ->with($user); - $this->Trait->Auth->expects($this->at(2)) - ->method('redirectUrl') - ->will($this->returnValue($redirectLoginOK)); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with($redirectLoginOK); - $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) - ->disableOriginalConstructor() - ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) - ->getMock(); - $this->Trait->login(); - } - - /** - * test - * - * @return void - */ - public function testAfterIdentifyEmptyUser() - { - $this->_mockDispatchEvent(new Event('event')); - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is']) - ->getMock(); - $this->Trait->request->expects($this->any()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) - ->disableOriginalConstructor() - ->getMock(); - $user = []; - $this->Trait->Auth->expects($this->once()) - ->method('identify') - ->will($this->returnValue($user)); - $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['error']) - ->disableOriginalConstructor() - ->getMock(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Username or password is incorrect', 'default', [], 'auth'); - $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) - ->disableOriginalConstructor() - ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) - ->getMock(); - $this->Trait->login(); - } - - /** - * test - * - * @return void - */ - public function testAfterIdentifyEmptyUserSocialLogin() - { - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') - ->setMethods(['dispatchEvent', 'redirect', '_isSocialLogin']) - ->getMockForTrait(); - $this->Trait->expects($this->any()) - ->method('_isSocialLogin') - ->will($this->returnValue(true)); - $this->_mockDispatchEvent(new Event('event')); - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is']) - ->getMock(); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) - ->disableOriginalConstructor() - ->getMock(); - - $this->Trait->login(); - } - - /** - * test - * - * @return void - */ - public function testLoginBeforeLoginReturningArray() - { - $user = [ - 'id' => 1 - ]; - $event = new Event('event'); - $event->result = $user; - $this->Trait->expects($this->at(0)) - ->method('dispatchEvent') - ->with(UsersAuthComponent::EVENT_BEFORE_LOGIN) - ->will($this->returnValue($event)); - $this->Trait->expects($this->at(1)) - ->method('dispatchEvent') - ->with(UsersAuthComponent::EVENT_AFTER_LOGIN) - ->will($this->returnValue(new Event('name'))); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setUser', 'redirectUrl']) - ->disableOriginalConstructor() - ->getMock(); - $redirectLoginOK = '/'; - $this->Trait->Auth->expects($this->once()) - ->method('setUser') - ->with($user); - $this->Trait->Auth->expects($this->once()) - ->method('redirectUrl') - ->will($this->returnValue($redirectLoginOK)); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with($redirectLoginOK); - $this->Trait->login(); - } - - /** - * test - * - * @return void - */ - public function testLoginBeforeLoginReturningStoppedEvent() - { - $event = new Event('event'); - $event->result = '/'; - $event->stopPropagation(); - $this->Trait->expects($this->at(0)) - ->method('dispatchEvent') - ->with(UsersAuthComponent::EVENT_BEFORE_LOGIN) - ->will($this->returnValue($event)); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with('/'); - $this->Trait->login(); - } - - /** - * test - * - * @return void - */ - public function testLoginGet() - { - $this->_mockDispatchEvent(new Event('event')); - $socialLogin = Configure::read('Users.Social.login'); - Configure::write('Users.Social.login', false); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user']) - ->disableOriginalConstructor() - ->getMock(); - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is']) - ->disableOriginalConstructor() - ->getMock(); - $this->Trait->request->expects($this->at(0)) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); - $this->Trait->request->expects($this->at(1)) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); - $this->Trait->login(); - Configure::write('Users.Social.login', $socialLogin); - } - - /** - * test - * - * @return void - */ - public function testLogout() - { - $this->_mockDispatchEvent(new Event('event')); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['logout', 'user']) - ->disableOriginalConstructor() - ->getMock(); - $redirectLogoutOK = '/'; - $this->Trait->Auth->expects($this->once()) - ->method('logout') - ->will($this->returnValue($redirectLogoutOK)); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with($redirectLogoutOK); - $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['success']) - ->disableOriginalConstructor() - ->getMock(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('You\'ve successfully logged out'); - $this->Trait->logout(); - } - - /** - * test - * - * @return void - */ - public function testFailedSocialLoginMissingEmail() - { - $event = new Entity(); - $event->data = [ - 'exception' => new MissingEmailException('Email not present'), - 'rawData' => [ - 'id' => 11111, - 'username' => 'user-1' - ] - ]; - $this->_mockFlash(); - $this->_mockRequestGet(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Please enter your email'); - - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); - - $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); - } - - /** - * test - * - * @return void - */ - public function testFailedSocialUserNotActive() - { - $event = new Entity(); - $event->data = [ - 'exception' => new UserNotActiveException('Facebook user-1'), - 'rawData' => [ - 'id' => 111111, - 'username' => 'user-1' - ] - ]; - $this->_mockFlash(); - $this->_mockRequestGet(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Your user has not been validated yet. Please check your inbox for instructions'); - - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - - $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); - } - - /** - * test - * - * @return void - */ - public function testFailedSocialUserAccountNotActive() - { - $event = new Entity(); - $event->data = [ - 'exception' => new AccountNotActiveException('Facebook user-1'), - 'rawData' => [ - 'id' => 111111, - 'username' => 'user-1' - ] - ]; - $this->_mockFlash(); - $this->_mockRequestGet(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Your social account has not been validated yet. Please check your inbox for instructions'); - - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - - $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); - } - - /** - * test - * - * @return void - */ - public function testFailedSocialUserAccount() - { - $event = new Entity(); - $event->data = [ - 'rawData' => [ - 'id' => 111111, - 'username' => 'user-1' - ] - ]; - $this->_mockFlash(); - $this->_mockRequestGet(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Issues trying to log in with your social account'); - - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - - $this->Trait->failedSocialLogin(null, $event->data['rawData'], true); - } - - /** - * testVerifyHappy - * - */ - public function testVerifyHappy() - { - Configure::write('Users.GoogleAuthenticator.login', true); - - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is', 'getData', 'allow', 'getSession']) - ->getMock(); - $this->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); - - $this->_mockSession([ - 'temporarySession' => [ - 'id' => 1, - 'secret_verified' => 1, - ] - ]); - $this->Trait->verify(); - } - - /** - * testVerifyNoUser - * - */ - public function testVerifyNoUser() - { - Configure::write('Users.GoogleAuthenticator.login', true); - - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is', 'getData', 'allow', 'getSession']) - ->getMock(); - $this->Trait->request->expects($this->never()) - ->method('is') - ->with('post'); - $this->_mockSession([]); - $this->_mockFlash(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Invalid request.'); - $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) - ->disableOriginalConstructor() - ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) - ->getMock(); - $this->Trait->verify(); - } - - /** - * testVerifyHappy - * - */ - public function testVerifyNotEnabled() - { - $this->_mockFlash(); - Configure::write('Users.GoogleAuthenticator.login', false); - $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) - ->disableOriginalConstructor() - ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) - ->getMock(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Please enable Google Authenticator first.'); - $this->Trait->verify(); - } - - /** - * testVerifyHappy - * - */ - public function testVerifyGetShowQR() - { - Configure::write('Users.GoogleAuthenticator.login', true); - - $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) - ->disableOriginalConstructor() - ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) - ->getMock(); - - $this->Trait->request = $this->getMockBuilder(ServerRequest::class) - ->setMethods(['is', 'getData', 'allow', 'getSession']) - ->getMock(); - $this->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); - $this->_mockSession([ - 'temporarySession' => [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'email' => 'email@example.com', - 'secret_verified' => 0, - ] - ]); - $this->Trait->GoogleAuthenticator->expects($this->at(0)) - ->method('createSecret') - ->will($this->returnValue('newSecret')); - $this->Trait->GoogleAuthenticator->expects($this->at(1)) - ->method('getQRCodeImageAsDataUri') - ->with('email@example.com', 'newSecret') - ->will($this->returnValue('newDataUriGenerated')); - $this->Trait->expects($this->at(0)) - ->method('set') - ->with(['secretDataUri' => 'newDataUriGenerated']); - $this->Trait->verify(); - } - - /** - * Tests that a GET request causes a a new secret to be generated in case it's - * not already present in the session. - */ - public function testVerifyGetGeneratesNewSecret() - { - Configure::write('Users.GoogleAuthenticator.login', true); - - $this->Trait->GoogleAuthenticator = $this - ->getMockBuilder(GoogleAuthenticatorComponent::class) - ->disableOriginalConstructor() - ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) - ->getMock(); - - $this->Trait->request = $this - ->getMockBuilder(ServerRequest::class) - ->setMethods(['is', 'getData', 'allow', 'getSession']) - ->getMock(); - $this->Trait->request - ->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); - - $this->Trait->GoogleAuthenticator - ->expects($this->at(0)) - ->method('createSecret') - ->will($this->returnValue('newSecret')); - $this->Trait->GoogleAuthenticator - ->expects($this->at(1)) - ->method('getQRCodeImageAsDataUri') - ->with('email@example.com', 'newSecret') - ->will($this->returnValue('newDataUriGenerated')); - - $session = $this->_mockSession([ - 'temporarySession' => [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'email' => 'email@example.com', - 'secret_verified' => false, - ] - ]); - $this->Trait->verify(); - - $this->assertEquals( - [ - 'temporarySession' => [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'email' => 'email@example.com', - 'secret_verified' => false, - 'secret' => 'newSecret' - ] - ], - $session->read() - ); - } - - /** - * Tests that a GET request does not cause a new secret to be generated in case - * it's already present in the session. - */ - public function testVerifyGetDoesNotGenerateNewSecret() - { - Configure::write('Users.GoogleAuthenticator.login', true); - - $this->Trait->GoogleAuthenticator = $this - ->getMockBuilder(GoogleAuthenticatorComponent::class) - ->disableOriginalConstructor() - ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) - ->getMock(); - - $this->Trait->request = $this - ->getMockBuilder(ServerRequest::class) - ->setMethods(['is', 'getData', 'allow', 'getSession']) - ->getMock(); - $this->Trait->request - ->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); - - $this->Trait->GoogleAuthenticator - ->expects($this->never()) - ->method('createSecret'); - $this->Trait->GoogleAuthenticator - ->expects($this->at(0)) - ->method('getQRCodeImageAsDataUri') - ->with('email@example.com', 'alreadyPresentSecret') - ->will($this->returnValue('newDataUriGenerated')); - - $session = $this->_mockSession([ - 'temporarySession' => [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'email' => 'email@example.com', - 'secret_verified' => false, - 'secret' => 'alreadyPresentSecret' - ] - ]); - $this->Trait->verify(); - - $this->assertEquals( - [ - 'temporarySession' => [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'email' => 'email@example.com', - 'secret_verified' => false, - 'secret' => 'alreadyPresentSecret' - ] - ], - $session->read() - ); - } - - /** - * Tests that posting a valid code causes verification to succeed. - */ - public function testVerifyPostValidCode() - { - Configure::write('Users.GoogleAuthenticator.login', true); - - $this->_mockDispatchEvent(new Event('event')); - $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) - ->disableOriginalConstructor() - ->setMethods(['createSecret', 'verifyCode', 'getQRCodeImageAsDataUri']) - ->getMock(); - - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setUser', 'redirectUrl']) - ->disableOriginalConstructor() - ->getMock(); - - $this->Trait->request = $this->getMockBuilder(ServerRequest::class) - ->setMethods(['is', 'getData', 'allow', 'getSession']) - ->getMock(); - $this->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->with('code') - ->will($this->returnValue('123456')); - - $this->Trait->GoogleAuthenticator - ->expects($this->never()) - ->method('createSecret'); - $this->Trait->GoogleAuthenticator - ->expects($this->at(0)) - ->method('getQRCodeImageAsDataUri') - ->with('email@example.com', 'yyy') - ->will($this->returnValue('newDataUriGenerated')); - $this->Trait->GoogleAuthenticator - ->expects($this->at(1)) - ->method('verifyCode') - ->with('yyy', '123456') - ->will($this->returnValue(true)); - - $this->Trait->Auth - ->expects($this->at(0)) - ->method('setUser') - ->with([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'email' => 'email@example.com', - 'secret_verified' => true - ]); - $this->Trait->Auth - ->expects($this->at(1)) - ->method('redirectUrl') - ->will($this->returnValue('/')); - - $this->assertFalse($this->table->exists([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'secret_verified' => true - ])); - - $session = $this->_mockSession([ - 'temporarySession' => [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'email' => 'email@example.com', - 'secret_verified' => false, - 'secret' => 'yyy' - ] - ]); - $this->Trait->verify(); - - $this->assertTrue($this->table->exists([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'secret_verified' => true - ])); - - $this->assertEmpty($session->read()); - } - - /** - * Tests that posting and invalid code causes verification to fail. - */ - public function testVerifyPostInvalidCode() - { - Configure::write('Users.GoogleAuthenticator.login', true); - - $this->Trait->GoogleAuthenticator = $this - ->getMockBuilder(GoogleAuthenticatorComponent::class) - ->disableOriginalConstructor() - ->setMethods(['createSecret', 'verifyCode', 'getQRCodeImageAsDataUri']) - ->getMock(); - - $this->Trait->Auth = $this - ->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setUser']) - ->disableOriginalConstructor() - ->getMock(); - - $this->Trait->Flash = $this - ->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['error']) - ->disableOriginalConstructor() - ->getMock(); - - $this->Trait->request = $this - ->getMockBuilder(ServerRequest::class) - ->setMethods(['is', 'getData', 'allow', 'getSession']) - ->getMock(); - $this->Trait->request - ->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - $this->Trait->request - ->expects($this->once()) - ->method('getData') - ->with('code') - ->will($this->returnValue('invalid')); - - $this->Trait->GoogleAuthenticator - ->expects($this->never()) - ->method('createSecret'); - $this->Trait->GoogleAuthenticator - ->expects($this->at(0)) - ->method('getQRCodeImageAsDataUri') - ->with('email@example.com', 'yyy') - ->will($this->returnValue('newDataUriGenerated')); - $this->Trait->GoogleAuthenticator - ->expects($this->at(1)) - ->method('verifyCode') - ->with('yyy', 'invalid') - ->will($this->returnValue(false)); - - $this->Trait->Auth - ->expects($this->never()) - ->method('setUser'); - - $this->Trait->Flash - ->expects($this->once()) - ->method('error') - ->with('Verification code is invalid. Try again', 'default', [], 'auth'); - - $this->Trait - ->expects($this->once()) - ->method('redirect') - ->with([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - 'prefix' => false, - '?' => [] - ]); - - $this->assertFalse($this->table->exists([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'secret_verified' => true - ])); - - $session = $this->_mockSession([ - 'temporarySession' => [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'email' => 'email@example.com', - 'secret_verified' => false, - 'secret' => 'yyy' - ] - ]); - $this->Trait->verify(); - - $this->assertFalse($this->table->exists([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'secret_verified' => true - ])); - - $this->assertEmpty($session->read()); - } - - /** - * Mock session and mock session attributes - * - * @return \Cake\Http\Session - */ - protected function _mockSession($attributes) - { - $session = new \Cake\Http\Session(); - - foreach ($attributes as $field => $value) { - $session->write($field, $value); - } - - $this->Trait->request - ->expects($this->any()) - ->method('getSession') - ->willReturn($session); - - return $session; - } -} diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php deleted file mode 100644 index f4d292765..000000000 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ /dev/null @@ -1,470 +0,0 @@ -traitClassName = 'CakeDC\Users\Controller\Traits\PasswordManagementTrait'; - $this->traitMockMethods = ['set', 'redirect', 'validate', 'log', 'dispatchEvent']; - $this->mockDefaultEmail = true; - parent::setUp(); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - parent::tearDown(); - } - - /** - * test - * - * @return void - */ - public function testChangePasswordHappy() - { - $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(); - $this->_mockFlash(); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->will($this->returnValue([ - 'password' => 'new', - 'password_confirm' => 'new', - ])); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); - $this->Trait->Flash->expects($this->any()) - ->method('success') - ->with('Password has been changed successfully'); - $this->Trait->changePassword(); - $hasher = PasswordHasherFactory::build('Default'); - $this->assertTrue($hasher->check('new', $this->table->get('00000000-0000-0000-0000-000000000001')->password)); - } - - /** - * test - * - * @return void - */ - public function testChangePasswordWithError() - { - $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(); - $this->_mockFlash(); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->will($this->returnValue([ - 'password' => 'new', - 'password_confirm' => 'wrong_new', - ])); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Password could not be changed'); - $this->Trait->changePassword(); - } - - /** - * test - * - * @return void - */ - public function testChangePasswordWithAfterChangeEvent() - { - $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(); - $this->_mockFlash(); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->will($this->returnValue([ - 'password' => 'new', - 'password_confirm' => 'new', - ])); - $event = new Event('event'); - $event->result = [ - 'action' => 'newAction', - ]; - $this->Trait->expects($this->once()) - ->method('dispatchEvent') - ->will($this->returnValue($event)); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'newAction']); - $this->Trait->Flash->expects($this->any()) - ->method('success') - ->with('Password has been changed successfully'); - $this->Trait->changePassword(); - $hasher = PasswordHasherFactory::build('Default'); - $this->assertTrue($hasher->check('new', $this->table->get('00000000-0000-0000-0000-000000000001')->password)); - } - - /** - * test - * - * @return void - */ - public function testChangePasswordWithSamePassword() - { - $this->assertEquals( - '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', - $this->table->get('00000000-0000-0000-0000-000000000006')->password - ); - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); - $this->_mockFlash(); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->will($this->returnValue([ - 'current_password' => '12345', - 'password' => '12345', - 'password_confirm' => '12345', - ])); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('You cannot use the current password as the new one'); - $this->Trait->changePassword(); - } - - /** - * test - * - * @return void - */ - public function testChangePasswordWithEmptyCurrentPassword() - { - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); - $this->_mockFlash(); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->will($this->returnValue([ - 'current_password' => '', - 'password' => '54321', - 'password_confirm' => '54321', - ])); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Password could not be changed'); - $this->Trait->changePassword(); - } - - /** - * test - * - * @return void - */ - public function testChangePasswordWithWrongCurrentPassword() - { - $this->assertEquals( - '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', - $this->table->get('00000000-0000-0000-0000-000000000006')->password - ); - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); - $this->_mockFlash(); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->will($this->returnValue([ - 'current_password' => 'wrong-password', - 'password' => '12345', - 'password_confirm' => '12345', - ])); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('The current password does not match'); - $this->Trait->changePassword(); - } - - /** - * test - * - * @return void - */ - public function testChangePasswordWithInvalidUser() - { - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(['id' => '12312312-0000-0000-0000-000000000002', 'password' => 'invalid-pass']); - $this->_mockFlash(); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->will($this->returnValue([ - 'password' => 'new', - 'password_confirm' => 'new', - ])); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('User was not found'); - $this->Trait->changePassword(); - } - - /** - * test - * - * @return void - */ - public function testChangePasswordGetLoggedIn() - { - $this->_mockRequestGet(); - $this->_mockAuthLoggedIn(); - $this->Trait->expects($this->any()) - ->method('set') - ->will($this->returnCallback(function ($param1, $param2 = null) { - if ($param1 === 'validatePassword') { - TestCase::assertEquals($param2, true); - } - })); - $this->Trait->changePassword(); - } - - /** - * test - * - * @return void - */ - public function testChangePasswordGetNotLoggedInInsideResetPasswordFlow() - { - $this->_mockRequestGet(true); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockSession([ - Configure::read('Users.Key.Session.resetPasswordUserId') => '00000000-0000-0000-0000-000000000001' - ]); - $this->Trait->expects($this->any()) - ->method('set') - ->will($this->returnCallback(function ($param1, $param2 = null) { - if ($param1 === 'validatePassword') { - TestCase::assertEquals($param2, false); - } - })); - $this->Trait->changePassword(); - } - - /** - * test - * - * @return void - */ - public function testChangePasswordGetNotLoggedInOutsideResetPasswordFlow() - { - $this->_mockRequestGet(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('User was not found'); - $this->Trait->changePassword(); - } - - /** - * test - * - * @return void - */ - public function testResetPassword() - { - $token = 'token'; - $this->Trait->expects($this->once()) - ->method('validate') - ->with('password', $token); - $this->Trait->resetPassword($token); - } - - /** - * test - * - * @return void - */ - public function testRequestResetPasswordGet() - { - $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get('00000000-0000-0000-0000-000000000001')->token); - $this->_mockRequestGet(); - $this->_mockFlash(); - $this->Trait->request->expects($this->never()) - ->method('getData'); - $this->Trait->requestResetPassword(); - } - - /** - * test - * - * @return void - */ - public function testRequestPasswordHappy() - { - $this->assertEquals('6614f65816754310a5f0553436dd89e9', $this->table->get('00000000-0000-0000-0000-000000000002')->token); - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(); - $this->_mockFlash(); - $reference = 'user-2'; - $this->Trait->request->expects($this->once()) - ->method('getData') - ->with('reference') - ->will($this->returnValue($reference)); - $this->Trait->Flash->expects($this->any()) - ->method('success') - ->with('Please check your email to continue with password reset process'); - $this->Trait->requestResetPassword(); - $this->assertNotEquals('xxx', $this->table->get('00000000-0000-0000-0000-000000000002')->token); - } - - /** - * test - * - * @return void - */ - public function testRequestPasswordInvalidUser() - { - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(['id' => 'invalid-id', 'password' => 'invalid-pass']); - $this->_mockFlash(); - $reference = '12312312-0000-0000-0000-000000000002'; - $this->Trait->request->expects($this->once()) - ->method('getData') - ->with('reference') - ->will($this->returnValue($reference)); - $this->Trait->Flash->expects($this->any()) - ->method('error') - ->with('User 12312312-0000-0000-0000-000000000002 was not found'); - $this->Trait->requestResetPassword(); - } - - /** - * test - * - * @return void - */ - public function testRequestPasswordEmptyReference() - { - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(['id' => 'invalid-id', 'password' => 'invalid-pass']); - $this->_mockFlash(); - $reference = ''; - $this->Trait->request->expects($this->once()) - ->method('getData') - ->with('reference') - ->will($this->returnValue($reference)); - $this->Trait->Flash->expects($this->any()) - ->method('error') - ->with('Token could not be reset'); - $this->Trait->requestResetPassword(); - } - - /** - * @dataProvider ensureUserActiveForResetPasswordFeature - * - * @return void - */ - public function testEnsureUserActiveForResetPasswordFeature($ensureActive) - { - $expectError = $this->never(); - - if ($ensureActive) { - Configure::write('Users.Registration.ensureActive', true); - $expectError = $this->once(); - } - - $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get('00000000-0000-0000-0000-000000000001')->token); - $this->_mockRequestPost(); - $this->_mockFlash(); - $reference = 'user-1'; - $this->Trait->request->expects($this->once()) - ->method('getData') - ->with('reference') - ->will($this->returnValue($reference)); - $this->Trait->Flash->expects($expectError) - ->method('error') - ->with('The user is not active'); - $this->Trait->requestResetPassword(); - $this->assertNotEquals('xxx', $this->table->get('00000000-0000-0000-0000-000000000001')->token); - } - - public function ensureUserActiveForResetPasswordFeature() - { - $ensureActive = true; - $defaultBehavior = false; - - return [ - [$ensureActive], - [$defaultBehavior] - ]; - } - - /** - * @dataProvider ensureGoogleAuthenticatorResets - * - * @return void - */ - public function testRequestGoogleAuthTokenResetWithValidUser($userId, $entityId, $method, $msg) - { - $this->_mockRequestPost(); - $this->_mockFlash(); - - $user = $this->table->get($userId); - - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'config']) - ->disableOriginalConstructor() - ->getMock(); - - $this->Trait->Auth->expects($this->any()) - ->method('user') - ->will($this->returnValue($user)); - - $this->Trait->Flash->expects($this->any()) - ->method($method) - ->with($msg); - - $this->Trait->resetGoogleAuthenticator($entityId); - } - - public function ensureGoogleAuthenticatorResets() - { - $error = 'error'; - $success = 'success'; - $errorMsg = 'You are not allowed to reset users Google Authenticator token'; - $successMsg = 'Google Authenticator token was successfully reset'; - - return [ - //is_superuser = true. - ['00000000-0000-0000-0000-000000000003', null, $success, $successMsg], - //is_superuser = true. - ['00000000-0000-0000-0000-000000000001', null, $success, $successMsg], - //is_superuser = false, and not his profile. - ['00000000-0000-0000-0000-000000000004', '00000000-0000-0000-0000-000000000001', $error, $errorMsg], - //is_superuser = false, editing own record. - ['00000000-0000-0000-0000-000000000004', '00000000-0000-0000-0000-000000000004', $success, $successMsg], - //is_superuser = false, and no entity-id given. - ['00000000-0000-0000-0000-000000000004', null, $error, $errorMsg], - ]; - } -} diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php deleted file mode 100644 index f0ab42c68..000000000 --- a/tests/TestCase/Controller/Traits/ProfileTraitTest.php +++ /dev/null @@ -1,113 +0,0 @@ -traitClassName = 'CakeDC\Users\Controller\Traits\ProfileTrait'; - $this->traitMockMethods = ['set', 'getUsersTable', 'redirect', 'validate']; - parent::setUp(); - } - - /** - * test - * - * @return void - */ - public function testProfileGetNotLoggedInUserNotFound() - { - $userId = '00000000-0000-0000-0000-000000000000'; //not found - $this->_mockRequestGet(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('User was not found'); - $this->Trait->profile($userId); - } - - /** - * test - * - * @return void - */ - public function testProfileGetLoggedInUserNotFound() - { - $userId = '00000000-0000-0000-0000-000000000000'; //not found - $this->_mockRequestGet(); - $this->_mockAuthLoggedIn(); - $this->_mockFlash(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('User was not found'); - $this->Trait->profile($userId); - } - - /** - * test - * - * @return void - */ - public function testProfileGetNotLoggedInEmptyId() - { - $this->_mockRequestGet(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Not authorized, please login first'); - $this->Trait->profile(); - } - - /** - * test - * - * @return void - */ - public function testProfileGetLoggedInMyProfile() - { - $this->_mockRequestGet(); - $this->_mockAuthLoggedIn(); - $this->_mockFlash(); - $this->Trait->expects($this->any()) - ->method('set') - ->will($this->returnCallback(function ($param1, $param2 = null) { - if ($param1 === 'avatarPlaceholder') { - BaseTraitTest::assertEquals('CakeDC/Users.avatar_placeholder.png', $param2); - } elseif (is_array($param1)) { - BaseTraitTest::assertEquals('user-1', $param1['user']->username); - } - })); - $this->Trait->profile(); - } -} diff --git a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php deleted file mode 100644 index a72250221..000000000 --- a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php +++ /dev/null @@ -1,123 +0,0 @@ -Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait') - ->setMethods(['_getReCaptchaInstance']) - ->getMockForTrait(); - } - - /** - * tearDown callback - * - * @return void - */ - public function tearDown() - { - parent::tearDown(); - } - - /** - * testValidateValidReCaptcha - * - * @return void - */ - public function testValidateValidReCaptcha() - { - $ReCaptcha = $this->getMockBuilder('ReCaptcha\ReCaptcha') - ->setMethods(['verify']) - ->disableOriginalConstructor() - ->getMock(); - $Response = $this->getMockBuilder('ReCaptcha\Response') - ->setMethods(['isSuccess']) - ->disableOriginalConstructor() - ->getMock(); - $Response->expects($this->any()) - ->method('isSuccess') - ->will($this->returnValue(true)); - $ReCaptcha->expects($this->any()) - ->method('verify') - ->with('value') - ->will($this->returnValue($Response)); - $this->Trait->expects($this->any()) - ->method('_getReCaptchaInstance') - ->will($this->returnValue($ReCaptcha)); - $this->Trait->validateReCaptcha('value', '255.255.255.255'); - } - - /** - * testValidateInvalidReCaptcha - * - * @return void - */ - public function testValidateInvalidReCaptcha() - { - $ReCaptcha = $this->getMockBuilder('ReCaptcha\ReCaptcha') - ->setMethods(['verify']) - ->disableOriginalConstructor() - ->getMock(); - $Response = $this->getMockBuilder('ReCaptcha\Response') - ->setMethods(['isSuccess']) - ->disableOriginalConstructor() - ->getMock(); - $Response->expects($this->any()) - ->method('isSuccess') - ->will($this->returnValue(false)); - $ReCaptcha->expects($this->any()) - ->method('verify') - ->with('invalid') - ->will($this->returnValue($Response)); - $this->Trait->expects($this->any()) - ->method('_getReCaptchaInstance') - ->will($this->returnValue($ReCaptcha)); - $this->Trait->validateReCaptcha('invalid', '255.255.255.255'); - } - - public function testGetRecaptchaInstance() - { - Configure::write('Users.reCaptcha.secret', 'secret'); - $trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait')->getMockForTrait(); - $method = new ReflectionMethod(get_class($trait), '_getReCaptchaInstance'); - $method->setAccessible(true); - $method->invokeArgs($trait, []); - $this->assertNotEmpty($method->invoke($trait)); - } - - public function testGetRecaptchaInstanceNull() - { - $trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait')->getMockForTrait(); - $method = new ReflectionMethod(get_class($trait), '_getReCaptchaInstance'); - $method->setAccessible(true); - $method->invokeArgs($trait, []); - $this->assertNull($method->invoke($trait)); - } - - public function testValidateReCaptchaFalse() - { - $trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait')->getMockForTrait(); - $this->assertFalse($this->Trait->validateReCaptcha('value', '255.255.255.255')); - } -} diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php deleted file mode 100644 index 6050b9bda..000000000 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ /dev/null @@ -1,399 +0,0 @@ -traitClassName = 'CakeDC\Users\Controller\Traits\RegisterTrait'; - $this->traitMockMethods = ['validate', 'dispatchEvent', 'set', 'validateReCaptcha', 'redirect']; - $this->mockDefaultEmail = true; - parent::setUp(); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - parent::tearDown(); - } - - /** - * test - * - * @return void - */ - public function testValidateEmail() - { - $token = 'token'; - $this->Trait->expects($this->once()) - ->method('validate') - ->with('email', $token); - $this->Trait->validateEmail($token); - } - - /** - * test - * - * @return void - */ - public function testRegister() - { - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestPost(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockDispatchEvent(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Please validate your account before log in'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->will($this->returnValue([ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ])); - - $this->Trait->register(); - - $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); - } - - /** - * Triggering beforeRegister event and not able to register the user - * - * @return void - */ - public function testRegisterWithEventFalseResult() - { - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestPost(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockDispatchEvent(new Event('Users.Component.UsersAuth.beforeRegister'), ['username' => 'hello']); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('The user could not be saved'); - $this->Trait->expects($this->never()) - ->method('redirect'); - $this->Trait->request->expects($this->never()) - ->method('is'); - - $this->Trait->register(); - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - } - - /** - * Triggering beforeRegister event and registering the user successfully - * - * @return void - */ - public function testRegisterWithEventSuccessResult() - { - $data = [ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ]; - - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestPost(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockDispatchEvent(new Event('Users.Component.UsersAuth.beforeRegister'), $data); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->will($this->returnValue($data)); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Please validate your account before log in'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->request->expects($this->never()) - ->method('is'); - - $this->Trait->register(); - $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); - } - - /** - * test - * - * @return void - */ - public function testRegisterReCaptcha() - { - Configure::write('Users.reCaptcha.registration', true); - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestPost(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockDispatchEvent(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Please validate your account before log in'); - $this->Trait->expects($this->once()) - ->method('validateRecaptcha') - ->will($this->returnValue(true)); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->request->expects($this->at(0)) - ->method('getData') - ->with() - ->will($this->returnValue([ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ])); - - $this->Trait->register(); - - $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); - } - - /** - * test - * - * @return void - */ - public function testRegisterValidationErrors() - { - Configure::write('Users.reCaptcha.registration', true); - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestPost(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockDispatchEvent(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('The user could not be saved'); - $this->Trait->expects($this->once()) - ->method('validateRecaptcha') - ->will($this->returnValue(true)); - $this->Trait->expects($this->never()) - ->method('redirect'); - $this->Trait->request->expects($this->at(0)) - ->method('getData') - ->with() - ->will($this->returnValue([ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'not-matching', - 'tos' => 1 - ])); - - $this->Trait->register(); - - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - } - - /** - * test - * - * @return void - */ - public function testRegisterRecaptchaNotValid() - { - Configure::write('Users.reCaptcha.registration', true); - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestPost(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockDispatchEvent(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Invalid reCaptcha'); - $this->Trait->expects($this->once()) - ->method('validateRecaptcha') - ->will($this->returnValue(false)); - $this->Trait->request->expects($this->at(0)) - ->method('getData') - ->with() - ->will($this->returnValue([ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ])); - - $this->Trait->register(); - - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - } - - /** - * test - * - * @return void - */ - public function testRegisterGet() - { - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestGet(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockDispatchEvent(); - $this->Trait->Flash->expects($this->never()) - ->method('success'); - $this->Trait->expects($this->never()) - ->method('validateRecaptcha'); - $this->Trait->expects($this->never()) - ->method('redirect'); - $this->Trait->register(); - - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - } - - /** - * test - * - * @return void - */ - public function testRegisterRecaptchaDisabled() - { - Configure::write('Users.Registration.reCaptcha', false); - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestPost(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockDispatchEvent(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Please validate your account before log in'); - $this->Trait->expects($this->never()) - ->method('validateRecaptcha'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->request->expects($this->at(0)) - ->method('getData') - ->with() - ->will($this->returnValue([ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ])); - - $this->Trait->register(); - - $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); - } - - /** - * test - * - * @return void - * @expectedException Cake\Http\Exception\NotFoundException - */ - public function testRegisterNotEnabled() - { - Configure::write('Users.Registration.active', false); - $this->_mockRequestPost(); - $this->_mockAuth(); - $this->_mockFlash(); - $this->_mockDispatchEvent(); - $this->Trait->register(); - } - - /** - * test - * - * @return void - */ - public function testRegisterLoggedInUserAllowed() - { - Configure::write('Users.Registration.allowLoggedIn', true); - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(); - $this->_mockFlash(); - $this->_mockDispatchEvent(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Please validate your account before log in'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->request->expects($this->at(0)) - ->method('getData') - ->with() - ->will($this->returnValue([ - 'username' => 'testRegistration', - 'password' => 'password', - 'email' => 'test-registration@example.com', - 'password_confirm' => 'password', - 'tos' => 1 - ])); - - $this->Trait->register(); - - $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); - } - - /** - * test - * - * @return void - */ - public function testRegisterLoggedInUserNotAllowed() - { - Configure::write('Users.Registration.allowLoggedIn', false); - $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); - $this->_mockRequestPost(); - $this->_mockAuthLoggedIn(); - $this->_mockFlash(); - $this->_mockDispatchEvent(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('You must log out to register a new user account'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(Configure::read('Users.Profile.route')); - $this->Trait->request->expects($this->never()) - ->method('getData') - ->with(); - - $this->Trait->register(); - } -} diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php deleted file mode 100644 index be5358db3..000000000 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ /dev/null @@ -1,306 +0,0 @@ -traitClassName = 'CakeDC\Users\Controller\Traits\SimpleCrudTrait'; - $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set', 'loadModel', 'paginate']; - parent::setUp(); - $viewVarsContainer = $this; - $this->Trait->expects($this->any()) - ->method('set') - ->will($this->returnCallback(function ($param1, $param2 = null) use ($viewVarsContainer) { - $viewVarsContainer->viewVars[$param1] = $param2; - })); - $this->Trait->expects($this->once()) - ->method('loadModel') - ->will($this->returnValue($this->table)); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - $this->viewVars = null; - parent::tearDown(); - } - - /** - * test - * - * @return void - */ - public function testIndex() - { - $this->Trait->expects($this->once()) - ->method('paginate') - ->with($this->table) - ->will($this->returnValue([])); - $this->Trait->index(); - $expected = [ - 'Users' => [], - 'tableAlias' => 'Users', - '_serialize' => [ - 'Users', - 'tableAlias' - ] - ]; - $this->assertSame($expected, $this->viewVars); - } - - /** - * test - * - * @return void - */ - public function testView() - { - $id = '00000000-0000-0000-0000-000000000001'; - $this->Trait->view($id); - $expected = [ - 'Users' => $this->table->get($id), - 'tableAlias' => 'Users', - '_serialize' => [ - 'Users', - 'tableAlias' - ] - ]; - $this->assertEquals($expected, $this->viewVars); - } - - /** - * test - * - * @return void - * @expectedException Cake\Datasource\Exception\RecordNotFoundException - */ - public function testViewNotFound() - { - $this->Trait->view('00000000-0000-0000-0000-000000000000'); - } - - /** - * test - * - * @return void - * @expectedException Cake\Datasource\Exception\InvalidPrimaryKeyException - */ - public function testViewInvalidPK() - { - $this->Trait->view(); - } - - /** - * test - * - * @return void - */ - public function testAddGet() - { - $this->_mockRequestGet(); - $this->Trait->add(); - $expected = [ - 'Users' => $this->table->newEntity(), - 'tableAlias' => 'Users', - '_serialize' => [ - 'Users', - 'tableAlias' - ] - ]; - $this->assertEquals($expected, $this->viewVars); - } - - /** - * test - * - * @return void - */ - public function testAddPostHappy() - { - $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); - $this->_mockRequestPost(); - $this->_mockFlash(); - $this->Trait->request->expects($this->at(0)) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - $this->Trait->request->expects($this->at(1)) - ->method('getData') - ->with() - ->will($this->returnValue([ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - ])); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('The User has been saved'); - - $this->Trait->add(); - - $this->assertSame(1, $this->table->find()->where(['username' => 'testuser'])->count()); - } - - /** - * test - * - * @return void - */ - public function testAddPostErrors() - { - $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); - $this->_mockRequestPost(); - $this->_mockFlash(); - $this->Trait->request->expects($this->at(0)) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - $this->Trait->request->expects($this->at(1)) - ->method('getData') - ->with() - ->will($this->returnValue([ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'first_name' => 'test', - 'last_name' => 'user', - ])); - - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('The User could not be saved'); - - $this->Trait->add(); - - $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); - } - - /** - * test - * - * @return void - */ - public function testEditPostHappy() - { - $this->assertEquals('user-1@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); - $this->_mockRequestPost(['patch', 'post', 'put']); - $this->_mockFlash(); - $this->Trait->request->expects($this->at(0)) - ->method('is') - ->with(['patch', 'post', 'put']) - ->will($this->returnValue(true)); - $this->Trait->request->expects($this->at(1)) - ->method('getData') - ->with() - ->will($this->returnValue([ - 'email' => 'newtestuser@test.com', - ])); - - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('The User has been saved'); - - $this->Trait->edit('00000000-0000-0000-0000-000000000001'); - - $this->assertEquals('newtestuser@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); - } - - /** - * test - * - * @return void - */ - public function testEditPostErrors() - { - $this->assertEquals('user-1@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); - $this->_mockRequestPost(['patch', 'post', 'put']); - $this->_mockFlash(); - $this->Trait->request->expects($this->at(0)) - ->method('is') - ->with(['patch', 'post', 'put']) - ->will($this->returnValue(true)); - $this->Trait->request->expects($this->at(1)) - ->method('getData') - ->with() - ->will($this->returnValue([ - 'email' => 'not-an-email', - ])); - - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('The User could not be saved'); - - $this->Trait->edit('00000000-0000-0000-0000-000000000001'); - - $this->assertEquals('user-1@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); - } - - /** - * test - * - * @return void - * @expectedException Cake\Datasource\Exception\RecordNotFoundException - */ - public function testDeleteHappy() - { - $this->assertNotEmpty($this->table->get('00000000-0000-0000-0000-000000000001')); - $this->_mockRequestPost(); - $this->Trait->request->expects($this->any()) - ->method('allow') - ->with(['post', 'delete']) - ->will($this->returnValue(true)); - - $this->_mockFlash(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('The User has been deleted'); - - $this->Trait->delete('00000000-0000-0000-0000-000000000001'); - - $this->table->get('00000000-0000-0000-0000-000000000001'); - } - - /** - * test - * - * @return void - * @expectedException Cake\Datasource\Exception\RecordNotFoundException - */ - public function testDeleteNotFound() - { - $this->assertNotEmpty($this->table->get('00000000-0000-0000-0000-000000000001')); - $this->_mockRequestPost(); - $this->Trait->request->expects($this->any()) - ->method('allow') - ->with(['post', 'delete']) - ->will($this->returnValue(true)); - - $this->Trait->delete('00000000-0000-0000-0000-000000000000'); - } -} diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php deleted file mode 100644 index 054bc7cb1..000000000 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ /dev/null @@ -1,180 +0,0 @@ -controller = $this->getMockBuilder('Cake\Controller\Controller') - ->setMethods(['header', 'redirect', 'render', '_stop']) - ->getMock(); - - $this->controller->Trait = $this->getMockForTrait( - 'CakeDC\Users\Controller\Traits\SocialTrait', - [], - '', - true, - true, - true, - ['_getOpauthInstance', 'redirect', '_generateOpauthCompleteUrl', '_afterIdentifyUser', '_validateRegisterPost'] - ); - } - - public function tearDown() - { - parent::tearDown(); - } - - /** - * Test socialEmail - * - */ - public function testSocialEmail() - { - $session = $this->getMockBuilder('Cake\Http\Session') - ->setMethods(['check', 'delete']) - ->getMock(); - $session->expects($this->at(0)) - ->method('check') - ->with('Users.social') - ->will($this->returnValue('social_key')); - - $session->expects($this->at(1)) - ->method('delete') - ->with('Flash.auth'); - - $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['getSession']) - ->getMock(); - $this->controller->Trait->request->expects($this->any()) - ->method('getSession') - ->will($this->returnValue($session)); - - $this->controller->Trait->socialEmail(); - } - - /** - * Test socialEmail - * - * @expectedException \Cake\Http\Exception\NotFoundException - */ - public function testSocialEmailInvalid() - { - $session = $this->getMockBuilder('Cake\Http\Session') - ->setMethods(['check']) - ->getMock(); - $session->expects($this->once()) - ->method('check') - ->with('Users.social') - ->will($this->returnValue(null)); - - $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['getSession']) - ->getMock(); - $this->controller->Trait->request->expects($this->once()) - ->method('getSession') - ->will($this->returnValue($session)); - - $this->controller->Trait->socialEmail(); - } - - public function testSocialEmailPostValidateFalse() - { - $session = $this->getMockBuilder('Cake\Http\Session') - ->setMethods(['check', 'delete']) - ->getMock(); - $session->expects($this->any()) - ->method('check') - ->with('Users.social') - ->will($this->returnValue(true)); - - $session->expects($this->once()) - ->method('delete') - ->with('Flash.auth'); - - $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['getSession', 'is']) - ->getMock(); - $this->controller->Trait->request->expects($this->any()) - ->method('getSession') - ->will($this->returnValue($session)); - - $this->controller->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - - $this->controller->Trait->expects($this->once()) - ->method('_validateRegisterPost') - ->will($this->returnValue(false)); - - $this->controller->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['error']) - ->disableOriginalConstructor() - ->getMock(); - - $this->controller->Trait->Flash->expects($this->once()) - ->method('error') - ->with('The reCaptcha could not be validated'); - - $this->controller->Trait->socialEmail(); - } - - public function testSocialEmailPostValidateTrue() - { - $session = $this->getMockBuilder('Cake\Http\Session') - ->setMethods(['check', 'delete']) - ->getMock(); - $session->expects($this->any()) - ->method('check') - ->with('Users.social') - ->will($this->returnValue(true)); - - $session->expects($this->once()) - ->method('delete') - ->with('Flash.auth'); - - $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['getSession', 'is']) - ->getMock(); - $this->controller->Trait->request->expects($this->any()) - ->method('getSession') - ->will($this->returnValue($session)); - - $this->controller->Trait->request->expects($this->once()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - - $this->controller->Trait->expects($this->once()) - ->method('_validateRegisterPost') - ->will($this->returnValue(true)); - - $this->controller->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['identify']) - ->disableOriginalConstructor() - ->getMock(); - - $this->controller->Trait->Auth->expects($this->once()) - ->method('identify'); - - $this->controller->Trait->expects($this->once()) - ->method('_afterIdentifyUser'); - - $this->controller->Trait->socialEmail(); - } -} diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php deleted file mode 100644 index 3747ce850..000000000 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ /dev/null @@ -1,243 +0,0 @@ -traitClassName = 'CakeDC\Users\Controller\Traits\UserValidationTrait'; - $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; - $this->mockDefaultEmail = true; - parent::setUp(); - } - - /** - * test - * - * @return void - */ - public function testValidateHappyEmail() - { - $this->_mockFlash(); - $user = $this->table->findByToken('token-3')->first(); - $this->assertFalse($user->active); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('User account validated successfully'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->validate('email', 'token-3'); - $user = $this->table->findById($user->id)->first(); - $this->assertTrue($user->active); - } - - /** - * test - * - * @return void - */ - public function testValidateUserNotFound() - { - $this->_mockFlash(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Invalid token or user account already validated'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->validate('email', 'not-found'); - } - - /** - * test - * - * @return void - */ - public function testValidateTokenExpired() - { - $this->_mockFlash(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Token already expired'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->validate('email', '6614f65816754310a5f0553436dd89e9'); - } - - /** - * test - * - * @return void - */ - public function testValidateTokenExpiredWithOnExpiredEvent() - { - $event = new Event('event'); - $event->result = [ - 'action' => 'newAction', - ]; - $this->Trait->expects($this->once()) - ->method('dispatchEvent') - ->will($this->returnValue($event)); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'newAction']); - $this->Trait->validate('email', '6614f65816754310a5f0553436dd89e9'); - } - - /** - * test - * - * @return void - */ - public function testValidateInvalidOp() - { - $this->_mockFlash(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('Invalid validation type'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->validate('invalid-op', '6614f65816754310a5f0553436dd89e9'); - } - - /** - * test - * - * @return void - */ - public function testValidateHappyPassword() - { - $this->_mockRequestGet(); - $this->_mockFlash(); - $user = $this->table->findByToken('token-4')->first(); - $this->assertTrue($user->active); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Reset password token was validated successfully'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'changePassword']); - $this->Trait->validate('password', 'token-4'); - $user = $this->table->findById($user->id)->first(); - $this->assertTrue($user->active); - } - - /** - * test - * - * @return void - */ - public function testResendTokenValidationHappy() - { - $this->_mockRequestPost(); - $this->_mockFlash(); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->with('reference') - ->will($this->returnValue('user-3')); - - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Token has been reset successfully. Please check your email.'); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->resendTokenValidation(); - } - - /** - * test - * - * @return void - */ - public function testResendTokenValidationWithAfterResendTokenValidationEvent() - { - $this->_mockRequestPost(); - $this->_mockFlash(); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->with('reference') - ->will($this->returnValue('user-3')); - - $event = new Event('event'); - $event->result = [ - 'action' => 'newAction', - ]; - $this->Trait->expects($this->once()) - ->method('dispatchEvent') - ->will($this->returnValue($event)); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['action' => 'newAction']); - - $this->Trait->resendTokenValidation(); - } - - /** - * test - * - * @return void - */ - public function testResendTokenValidationAlreadyActive() - { - $this->_mockRequestPost(); - $this->_mockFlash(); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->with('reference') - ->will($this->returnValue('user-4')); - - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('User user-4 is already active'); - $this->Trait->expects($this->never()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->resendTokenValidation(); - } - - /** - * test - * - * @return void - */ - public function testResendTokenValidationNotFound() - { - $this->_mockRequestPost(); - $this->_mockFlash(); - $this->Trait->request->expects($this->once()) - ->method('getData') - ->with('reference') - ->will($this->returnValue('not-found')); - - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('User not-found was not found'); - $this->Trait->expects($this->never()) - ->method('redirect') - ->with(['action' => 'login']); - $this->Trait->resendTokenValidation(); - } -} diff --git a/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php b/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php deleted file mode 100644 index a42d842f9..000000000 --- a/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php +++ /dev/null @@ -1,43 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/AccountNotActiveExceptionTest.php b/tests/TestCase/Exception/AccountNotActiveExceptionTest.php deleted file mode 100644 index 9e08205d5..000000000 --- a/tests/TestCase/Exception/AccountNotActiveExceptionTest.php +++ /dev/null @@ -1,45 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/BadConfigurationExceptionTest.php b/tests/TestCase/Exception/BadConfigurationExceptionTest.php deleted file mode 100644 index 556b7258f..000000000 --- a/tests/TestCase/Exception/BadConfigurationExceptionTest.php +++ /dev/null @@ -1,43 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/MissingEmailExceptionTest.php b/tests/TestCase/Exception/MissingEmailExceptionTest.php deleted file mode 100644 index 299b51b3f..000000000 --- a/tests/TestCase/Exception/MissingEmailExceptionTest.php +++ /dev/null @@ -1,43 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/MissingProviderExceptionTest.php b/tests/TestCase/Exception/MissingProviderExceptionTest.php deleted file mode 100644 index 0020f3360..000000000 --- a/tests/TestCase/Exception/MissingProviderExceptionTest.php +++ /dev/null @@ -1,43 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/TokenExpiredExceptionTest.php b/tests/TestCase/Exception/TokenExpiredExceptionTest.php deleted file mode 100644 index 195ae5432..000000000 --- a/tests/TestCase/Exception/TokenExpiredExceptionTest.php +++ /dev/null @@ -1,43 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php b/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php deleted file mode 100644 index 529742c53..000000000 --- a/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php +++ /dev/null @@ -1,43 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/UserNotActiveExceptionTest.php b/tests/TestCase/Exception/UserNotActiveExceptionTest.php deleted file mode 100644 index 73616e68f..000000000 --- a/tests/TestCase/Exception/UserNotActiveExceptionTest.php +++ /dev/null @@ -1,43 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/UserNotFoundExceptionTest.php b/tests/TestCase/Exception/UserNotFoundExceptionTest.php deleted file mode 100644 index d8e12580c..000000000 --- a/tests/TestCase/Exception/UserNotFoundExceptionTest.php +++ /dev/null @@ -1,43 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/WrongPasswordExceptionTest.php b/tests/TestCase/Exception/WrongPasswordExceptionTest.php deleted file mode 100644 index 20b94bedb..000000000 --- a/tests/TestCase/Exception/WrongPasswordExceptionTest.php +++ /dev/null @@ -1,43 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php deleted file mode 100644 index ae79ca496..000000000 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ /dev/null @@ -1,172 +0,0 @@ -Email = $this->getMockBuilder('Cake\Mailer\Email') - ->setMethods(['setTo', 'setSubject', 'setViewVars', 'setTemplate']) - ->getMock(); - - $this->UsersMailer = $this->getMockBuilder('CakeDC\Users\Mailer\UsersMailer') - ->setConstructorArgs([$this->Email]) - ->setMethods(['setTo', 'setSubject', 'setViewVars', 'setTemplate']) - ->getMock(); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - unset($this->UsersMailer); - unset($this->Email); - parent::tearDown(); - } - - /** - * test sendValidationEmail - * - * @return void - */ - public function testValidation() - { - $table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $data = [ - 'first_name' => 'FirstName', - 'email' => 'test@example.com', - 'token' => '12345' - ]; - $user = $table->newEntity($data); - $this->UsersMailer->expects($this->once()) - ->method('setTo') - ->with($user['email']) - ->will($this->returnValue($this->Email)); - - $this->Email->expects($this->once()) - ->method('setSubject') - ->with('FirstName, Your account validation link') - ->will($this->returnValue($this->Email)); - - $this->Email->expects($this->once()) - ->method('setViewVars') - ->with($data) - ->will($this->returnValue($this->Email)); - - $this->invokeMethod($this->UsersMailer, 'validation', [$user]); - } - - /** - * test SocialAccountValidation - * - * @return void - */ - public function testSocialAccountValidation() - { - $social = TableRegistry::getTableLocator()->get('CakeDC/Users.SocialAccounts') - ->get('00000000-0000-0000-0000-000000000001', ['contain' => 'Users']); - - $this->UsersMailer->expects($this->once()) - ->method('setTo') - ->with('user-1@test.com') - ->will($this->returnValue($this->Email)); - - $this->Email->expects($this->once()) - ->method('setSubject') - ->with('first1, Your social account validation link') - ->will($this->returnValue($this->Email)); - - $this->Email->expects($this->once()) - ->method('setViewVars') - ->with(['user' => $social->user, 'socialAccount' => $social]) - ->will($this->returnValue($this->Email)); - - $this->invokeMethod($this->UsersMailer, 'socialAccountValidation', [$social->user, $social]); - } - - /** - * test sendValidationEmail including 'template' - * - * @return void - */ - public function testResetPassword() - { - $table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $data = [ - 'first_name' => 'FirstName', - 'email' => 'test@example.com', - 'token' => '12345' - ]; - $user = $table->newEntity($data); - $this->UsersMailer->expects($this->once()) - ->method('setTo') - ->with($user['email']) - ->will($this->returnValue($this->Email)); - - $this->Email->expects($this->once()) - ->method('setSubject') - ->with('FirstName, Your reset password link') - ->will($this->returnValue($this->Email)); - - $this->Email->expects($this->once()) - ->method('setViewVars') - ->with($data) - ->will($this->returnValue($this->Email)); - - $this->invokeMethod($this->UsersMailer, 'resetPassword', [$user]); - } - - /** - * Call protected/private method of a class. - * - * @param object &$object Instantiated object that we will run method on. - * @param string $methodName Method name to call - * @param array $parameters Array of parameters to pass into method. - * - * @return mixed Method return. - */ - public function invokeMethod(&$object, $methodName, $parameters = []) - { - $reflection = new \ReflectionClass(get_class($object)); - $method = $reflection->getMethod($methodName); - $method->setAccessible(true); - - return $method->invokeArgs($object, $parameters); - } -} diff --git a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php deleted file mode 100644 index 2134da7eb..000000000 --- a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php +++ /dev/null @@ -1,104 +0,0 @@ -table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $this->Behavior = new AuthFinderBehavior($this->table); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - unset($this->table, $this->Behavior); - parent::tearDown(); - } - - /** - * Test findActive method. - * - */ - public function testFindActive() - { - $actual = $this->table->find('active')->toArray(); - $this->assertCount(8, $actual); - $this->assertCount(8, Hash::extract($actual, '{n}[active=1]')); - $this->assertCount(0, Hash::extract($actual, '{n}[active=0]')); - } - - /** - * Test findAuth method. - * - * @expectedException \BadMethodCallException - * @expectedExceptionMessage Missing 'username' in options data - */ - public function testFindAuthBadMethodCallException() - { - $user = $this->table->find('auth'); - } - - /** - * Test findAuth method. - * - * @expected - */ - public function testFindAuth() - { - $user = $this->table - ->find('auth', ['username' => 'not-exist@email.com']) - ->toArray(); - $this->assertEmpty($user); - - $user = $this->table - ->find('auth', ['username' => 'user-2@test.com']) - ->first() - ->toArray(); - - $this->assertSame('00000000-0000-0000-0000-000000000002', Hash::get($user, 'id')); - $this->assertSame('user-2', Hash::get($user, 'username')); - } -} diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php deleted file mode 100644 index 0d2710ae0..000000000 --- a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php +++ /dev/null @@ -1,363 +0,0 @@ -Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $this->Behavior = new LinkSocialBehavior($this->Table); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - unset($this->Table, $this->Behavior); - parent::tearDown(); - } - - /** - * Test linkSocialAccount with facebook and not existing social account - * - * @param array $data Test input data - * @param string $userId User id to add social account - * @param array $result Expected result - * - * @author Marcelo Rocha - * @return void - * @dataProvider providerFacebookLinkSocialAccount - */ - public function testlinkSocialAccountFacebookProvider($data, $userId, $result) - { - $user = $this->Table->get($userId, [ - 'contain' => 'SocialAccounts' - ]); - $resultUser = $this->Behavior->linkSocialAccount($user, $data); - $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); - $actual = $resultUser->social_accounts[2]; - - $this->assertInstanceOf('\CakeDC\Users\Model\Entity\SocialAccount', $actual); - $actual->token_expires = $actual->token_expires->format('Y-m-d H:i:s'); - - foreach ($result as $property => $value) { - $this->assertEquals($value, $actual->$property); - } - - $result = $this->Table->SocialAccounts->exists(['id' => $actual->id]); - $this->assertTrue($result); - } - - /** - * Provider for linkSocialAccount with facebook and not existing social account - * - * @author Marcelo Rocha - * @return array - */ - public function providerFacebookLinkSocialAccount() - { - $expiresTime = new Time(); - $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); - - return [ - 'provider' => [ - 'data' => [ - 'id' => '9999911112255', //Reference existe mas provider google - 'username' => null, - 'full_name' => 'Full name', - 'first_name' => 'First name', - 'last_name' => 'Last name', - 'email' => 'user-1@test.com', - 'raw' => [ - 'id' => '9999911112255', - 'name' => 'Ful Name.', - 'first_name' => 'First Name', - 'last_name' => 'Last name', - 'email' => 'user-1@test.com', - 'picture' => [ - 'data' => [ - 'url' => 'data-url' - ] - ] - ], - 'credentials' => [ - 'token' => 'token', - 'secret' => null, - 'expires' => 1458423682 - ], - 'validated' => true, - 'link' => 'facebook-link-15579', - 'provider' => 'Facebook' - ], - 'user' => '00000000-0000-0000-0000-000000000001', - 'result' => [ - 'provider' => 'Facebook', - 'username' => null, - 'reference' => '9999911112255', - 'avatar' => '', - 'link' => 'facebook-link-15579', - 'description' => null, - 'token' => 'token', - 'token_secret' => null, - 'token_expires' => $tokenExpires, - 'user_id' => '00000000-0000-0000-0000-000000000001', - 'active' => true - - ] - ] - - ]; - } - - /** - * Test linkSocialAccount with facebook and could not save social account - * - * @param array $data Test input data - * @param string $userId User id to add social account - * @param array $result Expected result - * - * @author Marcelo Rocha - * @return void - * @dataProvider providerFacebookLinkSocialAccountErrorSaving - */ - public function testlinkSocialAccountErrorSavingFacebookProvider($data, $userId, $result) - { - $user = $this->Table->get($userId); - $resultUser = $this->Behavior->linkSocialAccount($user, $data); - $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); - $actual = $resultUser->social_accounts[0]; - $this->assertInstanceOf('\CakeDC\Users\Model\Entity\SocialAccount', $actual); - - $actual = $user->getErrors(); - - $expected = [ - 'social_accounts' => [ - [ - 'token' => [ - '_empty' => 'This field cannot be left empty' - ] - ] - ] - ]; - $this->assertEquals($expected, $actual); - - $error = $user->getErrors('social_accounts'); - $error = $error ? reset($error) : $message; - } - - /** - * Provider for linkSocialAccount with facebook and could not save social account - * - * @author Marcelo Rocha - * @return array - */ - public function providerFacebookLinkSocialAccountErrorSaving() - { - $expiresTime = new Time(); - $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); - - return [ - 'provider' => [ - 'data' => [ - 'id' => '9999911112255', //Reference existe mas provider google - 'username' => null, - 'full_name' => 'Full name', - 'first_name' => 'First name', - 'last_name' => 'Last name', - 'email' => 'user-1@test.com', - 'raw' => [ - 'id' => '9999911112255', - 'name' => 'Ful Name.', - 'first_name' => 'First Name', - 'last_name' => 'Last name', - 'email' => 'user-1@test.com', - 'picture' => [ - 'data' => [ - 'url' => 'data-url' - ] - ] - ], - 'credentials' => [ - 'token' => '', - 'secret' => null, - 'expires' => 1458423682 - ], - 'validated' => true, - 'link' => 'facebook-link-15579', - 'provider' => 'Facebook' - ], - 'user' => '00000000-0000-0000-0000-000000000001', - 'result' => [ - 'provider' => 'Facebook', - 'username' => null, - 'reference' => '9999911112255', - 'avatar' => '', - 'link' => 'facebook-link-15579', - 'description' => null, - 'token' => 'token', - 'token_secret' => null, - 'token_expires' => $tokenExpires, - 'user_id' => '00000000-0000-0000-0000-000000000001', - 'active' => true - - ] - ] - - ]; - } - - /** - * Test linkSocialAccount with facebook when account already exists - * - * @param array $data Test input data - * @param string $userId User id to add social account - * @param array $result Expected result - * - * @author Marcelo Rocha - * @return void - * @dataProvider providerFacebookLinkSocialAccountAccountExists - */ - public function testlinkSocialAccountFacebookProviderAccountExists($data, $userId, $result) - { - $user = $this->Table->get($userId); - $resultUser = $this->Behavior->linkSocialAccount($user, $data); - $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); - $this->assertFalse($resultUser->has('social_accounts')); - $expected = [ - 'social_accounts' => [ - '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') - ] - ]; - $actual = $user->getErrors(); - $this->assertEquals($expected, $actual); - - //Se for o usuĆ”rio que jĆ” esta associado entĆ£o okay - $socialAccount = $this->Table->SocialAccounts->find()->where([ - 'reference' => $data['id'], - 'provider' => $data['provider'] - ])->firstOrFail(); - - $userBase = $this->Table->get('00000000-0000-0000-0000-000000000002', [ - 'contain' => ['SocialAccounts'] - ]); - $resultUser = $this->Behavior->linkSocialAccount($userBase, $data); - $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); - $this->assertEquals([], $userBase->getErrors()); - - $actual = $resultUser->social_accounts[0]; - - $this->assertInstanceOf('\CakeDC\Users\Model\Entity\SocialAccount', $actual); - - $actual->token_expires = $actual->token_expires->format('Y-m-d H:i:s'); - foreach ($result as $property => $value) { - $this->assertEquals($value, $actual->$property); - } - } - - /** - * Provider for linkSocialAccount with facebook when account already exists - * - * @author Marcelo Rocha - * @return array - */ - public function providerFacebookLinkSocialAccountAccountExists() - { - $expiresTime = new Time(); - $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); - - return [ - 'provider' => [ - 'data' => [ - 'id' => 'reference-2-1', - 'username' => null, - 'full_name' => 'Full name', - 'first_name' => 'First name', - 'last_name' => 'Last name', - 'email' => 'email@example.com', - 'raw' => [ - 'id' => 'reference-2-1', - 'name' => 'Ful Name.', - 'first_name' => 'First Name', - 'last_name' => 'Last name', - 'email' => 'email@example.com', - 'picture' => [ - 'data' => [ - 'url' => 'data-url' - ] - ] - ], - 'credentials' => [ - 'token' => 'token', - 'secret' => null, - 'expires' => 1458423682 - ], - 'validated' => true, - 'link' => 'facebook-link-15579', - 'provider' => 'Facebook' - ], - 'user' => '00000000-0000-0000-0000-000000000001', - 'result' => [ - 'id' => '00000000-0000-0000-0000-000000000003', - 'provider' => 'Facebook', - 'username' => null, - 'reference' => 'reference-2-1', - 'avatar' => '', - 'link' => 'facebook-link-15579', - 'description' => null, - 'token' => 'token', - 'token_secret' => null, - 'token_expires' => $tokenExpires, - 'user_id' => '00000000-0000-0000-0000-000000000002', - 'active' => true - ] - ] - - ]; - } -} diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php deleted file mode 100644 index d25bac7aa..000000000 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ /dev/null @@ -1,237 +0,0 @@ -table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\PasswordBehavior') - ->setMethods(['_sendResetPasswordEmail']) - ->setConstructorArgs([$this->table]) - ->getMock(); - Email::setConfigTransport('test', [ - 'className' => 'Debug' - ]); - //$this->configEmail = Email::getConfig('default'); - Email::setConfig('default', [ - 'transport' => 'test', - 'from' => 'cakedc@example.com' - ]); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - unset($this->table, $this->Behavior); - Email::drop('default'); - Email::dropTransport('test'); - parent::tearDown(); - } - - /** - * Test resetToken - * - */ - public function testResetToken() - { - $user = $this->table->findByUsername('user-1')->first(); - $token = $user->token; - $this->Behavior->expects($this->never()) - ->method('_sendResetPasswordEmail') - ->with($user); - $result = $this->Behavior->resetToken('user-1', [ - 'expiration' => 3600, - 'checkActive' => true, - ]); - $this->assertNotEquals($token, $result->token); - $this->assertEmpty($result->activation_date); - $this->assertFalse($result->active); - } - - /** - * Test resetToken - * - */ - public function testResetTokenSendEmail() - { - $user = $this->table->findByUsername('user-1')->first(); - $token = $user->token; - $tokenExpires = $user->token_expires; - $this->Behavior->expects($this->once()) - ->method('_sendResetPasswordEmail'); - $result = $this->Behavior->resetToken('user-1', [ - 'expiration' => 3600, - 'checkActive' => true, - 'sendEmail' => true, - 'type' => 'password' - ]); - $this->assertNotEquals($token, $result->token); - $this->assertNotEquals($tokenExpires, $result->token_expires); - $this->assertEmpty($result->activation_date); - $this->assertFalse($result->active); - } - - /** - * Test resetToken - * - * @expectedException InvalidArgumentException - */ - public function testResetTokenWithNullParams() - { - $this->Behavior->resetToken(null); - } - - /** - * Test resetTokenNoExpiration - * - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Token expiration cannot be empty - */ - public function testResetTokenNoExpiration() - { - $this->Behavior->resetToken('ref'); - } - - /** - * Test resetToken - * - * @expectedException \CakeDC\Users\Exception\UserNotFoundException - */ - public function testResetTokenNotExistingUser() - { - $this->Behavior->resetToken('user-not-found', [ - 'expiration' => 3600 - ]); - } - - /** - * Test resetToken - * - * @expectedException \CakeDC\Users\Exception\UserAlreadyActiveException - */ - public function testResetTokenUserAlreadyActive() - { - $activeUser = TableRegistry::getTableLocator()->get('CakeDC/Users.Users')->findByUsername('user-4')->first(); - $this->assertTrue($activeUser->active); - $this->table = $this->getMockForModel('CakeDC/Users.Users', ['save']); - $this->table->expects($this->never()) - ->method('save'); - $this->Behavior->expects($this->never()) - ->method('_sendResetPasswordEmail'); - $this->Behavior->resetToken('user-4', [ - 'expiration' => 3600, - 'checkActive' => true, - ]); - } - - /** - * Test resetToken - * - * @expectedException \CakeDC\Users\Exception\UserNotActiveException - */ - public function testResetTokenUserNotActive() - { - $user = $this->table->findByUsername('user-1')->first(); - $this->Behavior->resetToken('user-1', [ - 'ensureActive' => true, - 'expiration' => 3600 - ]); - } - - /** - * Test resetToken - */ - public function testResetTokenUserActive() - { - $user = TableRegistry::getTableLocator()->get('CakeDC/Users.Users')->findByUsername('user-2')->first(); - $result = $this->Behavior->resetToken('user-2', [ - 'ensureActive' => true, - 'expiration' => 3600 - ]); - $this->assertEquals($user->id, $result->id); - } - - /** - * Test changePassword - */ - public function testChangePassword() - { - $user = TableRegistry::getTableLocator()->get('CakeDC/Users.Users')->findByUsername('user-6')->first(); - $user->current_password = '12345'; - $user->password = 'new'; - $user->password_confirmation = 'new'; - - $result = $this->Behavior->changePassword($user); - } - - /** - * test Email Override - */ - public function testEmailOverride() - { - $overrideMailer = $this->getMockBuilder(OverrideMailer::class) - ->setMethods(['send']) - ->getMock(); - Configure::write('Users.Email.mailerClass', OverrideMailer::class); - $this->Behavior = $this->getMockBuilder(PasswordBehavior::class) - ->setConstructorArgs([$this->table]) - ->setMethods(['getMailer']) - ->getMock(); - $overrideMailer->expects($this->once()) - ->method('send') - ->with('resetPassword') - ->willReturn(true); - $this->Behavior->expects($this->once()) - ->method('getMailer') - ->with(OverrideMailer::class) - ->willReturn($overrideMailer); - $this->Behavior->resetToken('user-1', [ - 'expiration' => 3600, - 'checkActive' => true, - 'sendEmail' => true, - 'type' => 'password' - ]); - } -} diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php deleted file mode 100644 index 0dfa3ffdf..000000000 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ /dev/null @@ -1,320 +0,0 @@ -get('CakeDC/Users.Users'); - $table->addBehavior('CakeDC/Users/Register.Register'); - $this->Table = $table; - $this->Behavior = $table->behaviors()->Register; - Email::setConfigTransport('test', [ - 'className' => 'Debug' - ]); - Email::setConfig('default', [ - 'transport' => 'test', - 'from' => 'cakedc@example.com' - ]); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - unset($this->Table, $this->Behavior); - Email::drop('default'); - Email::dropTransport('test'); - parent::tearDown(); - } - - /** - * Test register method - * - * @return void - */ - public function testValidateRegisterNoValidateEmail() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - 'tos' => 1 - ]; - $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 0]); - $this->assertTrue($result->active); - } - - /** - * Test register method - * - * @return void - */ - public function testValidateRegisterEmptyUser() - { - $user = []; - $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); - $this->assertFalse($result); - } - - /** - * Test register method - * - * @return void - */ - public function testValidateRegisterValidateEmailAndTos() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - 'tos' => 1 - ]; - $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); - $this->assertNotEmpty($result); - $this->assertFalse($result->active); - $this->assertNotEmpty($result->tos_date); - } - - /** - * Test register method - * - * @return void - */ - public function testValidateRegisterValidatorOption() - { - $this->Table = $this->getMockForModel('CakeDC/Users.Users', ['validationCustom', 'patchEntity', 'errors', 'save']); - - $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\RegisterBehavior') - ->setMethods(['getValidators', '_updateActive']) - ->setConstructorArgs([$this->Table]) - ->getMock(); - - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - 'tos' => 1 - ]; - - $this->Behavior->expects($this->never()) - ->method('getValidators'); - - $entityUser = $this->Table->newEntity($user); - - $this->Behavior->expects($this->once()) - ->method('_updateActive') - ->will($this->returnValue($entityUser)); - - $this->Table->expects($this->once()) - ->method('patchEntity') - ->with($this->Table->newEntity(), $user, ['validate' => 'custom']) - ->will($this->returnValue($entityUser)); - - $this->Table->expects($this->once()) - ->method('save') - ->with($entityUser) - ->will($this->returnValue($entityUser)); - - $result = $this->Behavior->register($this->Table->newEntity(), $user, ['validator' => 'custom', 'validate_email' => 1]); - $this->assertNotEmpty($result->tos_date); - } - - /** - * Test register method - * - */ - public function testValidateRegisterTosRequired() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - ]; - $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); - $this->assertFalse($result); - } - - /** - * Test register method - * - * @return void - */ - public function testValidateRegisterNoTosRequired() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - ]; - $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); - $this->assertNotEmpty($result); - } - - /** - * Test ActivateUser method - * - * @return void - */ - public function testActivateUser() - { - $user = $this->Table->find()->where(['id' => '00000000-0000-0000-0000-000000000001'])->first(); - $result = $this->Table->activateUser($user); - $this->assertTrue($result->active); - } - - /** - * Test Validate method - * - * @return void - */ - public function testValidate() - { - $result = $this->Table->validate('ae93ddbe32664ce7927cf0c5c5a5e59d', 'activateUser'); - $this->assertTrue($result->active); - $this->assertEmpty($result->token_expires); - } - - /** - * Test Validate method - * - * @return void - * @expectedException \CakeDC\Users\Exception\TokenExpiredException - */ - public function testValidateUserWithExpiredToken() - { - $this->Table->validate('token-5', 'activateUser'); - } - - /** - * Test Validate method - * - * @return void - * @expectedException \CakeDC\Users\Exception\UserNotFoundException - */ - public function testValidateNotExistingUser() - { - $this->Table->validate('not-existing-token', 'activateUser'); - } - - /** - * Test activateUser method - * - * @return void - */ - public function testActiveUserRemoveValidationToken() - { - $user = $this->Table->find()->where(['id' => '00000000-0000-0000-0000-000000000001'])->first(); - $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\RegisterBehavior') - ->setConstructorArgs([$this->Table]) - ->getMock(); - - $resultValidationToken = $user; - $resultValidationToken->token_expires = null; - $resultValidationToken->token = null; - - $this->Behavior->activateUser($user); - } - - /** - * Test register default role - * - * @return void - */ - public function testRegisterUsingDefaultRole() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - 'tos' => 1 - ]; - Configure::write('Users.Registration.defaultRole', false); - $result = $this->Table->register($this->Table->newEntity(), $user, [ - 'token_expiration' => 3600, - 'validate_email' => 0 - ]); - $this->assertSame('user', $result['role']); - } - - /** - * Test register not default role - * - * @return void - */ - public function testRegisterUsingCustomRole() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - 'tos' => 1 - ]; - Configure::write('Users.Registration.defaultRole', 'emperor'); - $result = $this->Table->register($this->Table->newEntity(), $user, [ - 'token_expiration' => 3600, - 'validate_email' => 0, - ]); - $this->assertSame('emperor', $result['role']); - } -} diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php deleted file mode 100644 index b9149c516..000000000 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ /dev/null @@ -1,141 +0,0 @@ -Table = TableRegistry::getTableLocator()->get('CakeDC/Users.SocialAccounts'); - $this->Behavior = $this->Table->behaviors()->SocialAccount; - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - unset($this->Table, $this->Behavior, $this->Email); - parent::tearDown(); - } - - /** - * Test validateEmail method - * - * @return void - */ - public function testValidateEmail() - { - $token = 'token-1234'; - $result = $this->Behavior->validateAccount(SocialAccountsTable::PROVIDER_FACEBOOK, 'reference-1-1234', $token); - $this->assertTrue($result->active); - $this->assertEquals($token, $result->token); - } - - /** - * Test validateEmail method - * - * @expectedException \Cake\Datasource\Exception\RecordNotFoundException - */ - public function testValidateEmailInvalidToken() - { - $this->Behavior->validateAccount(1, 'reference-1234', 'invalid-token'); - } - - /** - * Test validateEmail method - * - * @expectedException \Cake\Datasource\Exception\RecordNotFoundException - */ - public function testValidateEmailInvalidUser() - { - $this->Behavior->validateAccount(1, 'invalid-user', 'token-1234'); - } - - /** - * Test validateEmail method - * - * @expectedException CakeDC\Users\Exception\AccountAlreadyActiveException - */ - public function testValidateEmailActiveAccount() - { - $this->Behavior->validateAccount(SocialAccountsTable::PROVIDER_TWITTER, 'reference-1-1234', 'token-1234'); - } - - /** - * testAfterSaveSocialNotActiveUserNotActive - * don't send email, user is not active - * - * @return void - */ - public function testAfterSaveSocialNotActiveUserNotActive() - { - $event = new Event('eventName'); - $entity = $this->Table->find()->first(); - $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); - } - - /** - * testAfterSaveSocialActiveUserActive - * social account is active, don't send email - * - * @return void - */ - public function testAfterSaveSocialActiveUserActive() - { - $event = new Event('eventName'); - $entity = $this->Table->findById('00000000-0000-0000-0000-000000000003')->first(); - $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); - } - - /** - * testAfterSaveSocialActiveUserNotActive - * social account is active, don't send email - * - * @return void - */ - public function testAfterSaveSocialActiveUserNotActive() - { - $event = new Event('eventName'); - $entity = $this->Table->findById('00000000-0000-0000-0000-000000000002')->first(); - $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); - } -} diff --git a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php deleted file mode 100644 index 0582eac9b..000000000 --- a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php +++ /dev/null @@ -1,388 +0,0 @@ -Table = $this->getMockForModel('CakeDC/Users.Users', ['save']); - $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialBehavior') - ->setMethods(['randomString', '_updateActive', 'generateUniqueUsername']) - ->setConstructorArgs([$this->Table]) - ->getMock(); - } - - /** - * tearDown - * - * @return void - */ - public function tearDown() - { - unset($this->Table, $this->Behavior, $this->Email); - parent::tearDown(); - } - - /** - * Test socialLogin with facebook and not existing user - * - * @dataProvider providerFacebookSocialLogin - */ - public function testSocialLoginFacebookProvider($data, $options, $dataUser) - { - $user = $this->Table->newEntity($dataUser, ['associated' => ['SocialAccounts']]); - $user->password = '$2y$10$0QzszaIEpW1pYpoKJVf4DeqEAHtg9whiLTX/l3TcHAoOLF1bC9U.6'; - - $this->Behavior->expects($this->once()) - ->method('generateUniqueUsername') - ->with('email') - ->will($this->returnValue('username')); - - $this->Behavior->expects($this->once()) - ->method('randomString') - ->will($this->returnValue('password')); - - $this->Behavior->expects($this->once()) - ->method('_updateActive') - ->will($this->returnValue($user)); - - $this->Table->expects($this->once()) - ->method('save') - ->with($user) - ->will($this->returnValue($user)); - - $result = $this->Behavior->socialLogin($data, $options); - $this->assertEquals($result, $user); - } - - /** - * Test socialLogin with facebook and not existing user - * - * @dataProvider providerFacebookSocialLogin - */ - public function testSocialLoginFacebookProviderUsingEmail($data, $options, $dataUser) - { - $user = $this->Table->newEntity($dataUser, ['associated' => ['SocialAccounts']]); - $user->password = '$2y$10$0QzszaIEpW1pYpoKJVf4DeqEAHtg9whiLTX/l3TcHAoOLF1bC9U.6'; - - $this->Behavior->expects($this->once()) - ->method('generateUniqueUsername') - ->with('email') - ->will($this->returnValue('username')); - - $this->Behavior->expects($this->once()) - ->method('randomString') - ->will($this->returnValue('password')); - - $this->Behavior->expects($this->once()) - ->method('_updateActive') - ->will($this->returnValue($user)); - - $this->Table->expects($this->once()) - ->method('save') - ->with($user) - ->will($this->returnValue($user)); - - $this->Behavior->initialize(['username' => 'email']); - $result = $this->Behavior->socialLogin($data, $options); - $this->assertEquals($result, $user); - } - - /** - * Provider for socialLogin with facebook and not existing user - * - */ - public function providerFacebookSocialLogin() - { - return [ - 'provider' => [ - 'data' => [ - 'id' => 'facebook-id', - 'username' => null, - 'full_name' => 'Full name', - 'first_name' => 'First name', - 'last_name' => 'Last name', - 'email' => 'email@example.com', - 'raw' => [ - 'id' => '10153521527396318', - 'name' => 'Ful Name.', - 'first_name' => 'First Name', - 'last_name' => 'Last name', - 'email' => 'email@example.com', - 'picture' => [ - 'data' => [ - 'url' => 'data-url' - ] - ] - ], - 'credentials' => [ - 'token' => 'token', - 'secret' => null, - 'expires' => 1458423682 - ], - 'validated' => true, - 'link' => 'facebook-link', - 'provider' => 'Facebook' - ], - 'options' => [ - 'use_email' => true, - 'validate_email' => true, - 'token_expiration' => 3600 - ], - 'result' => [ - 'first_name' => 'First name', - 'last_name' => 'Last name', - 'username' => 'username', - 'email' => 'email@example.com', - 'password' => '$2y$10$oLPxCkKJ1TUCR6xJ1t0Wj.7Fznx49Wn4NZB2aJCmVvRMucaHuNyyO', - 'avatar' => null, - 'tos_date' => '2016-01-20 15:45:09', - 'gender' => null, - 'social_accounts' => [ - [ - 'provider' => 'Facebook', - 'username' => null, - 'reference' => '10153521527396318', - 'avatar' => '', - 'link' => 'facebook-link', - 'description' => null, - 'token' => 'token', - 'token_secret' => null, - 'token_expires' => '2016-03-19 21:41:22', - 'data' => '-', - 'active' => true - ] - ], - 'activation_date' => '2016-01-20 15:45:09', - 'active' => true, - ] - ] - - ]; - } - - /** - * Test socialLogin with facebook with existing and active user - * - * @dataProvider providerFacebookSocialLoginExistingReference - */ - public function testSocialLoginExistingReference($data, $options) - { - $this->Behavior->expects($this->never()) - ->method('generateUniqueUsername'); - - $this->Behavior->expects($this->never()) - ->method('randomString'); - - $this->Behavior->expects($this->never()) - ->method('_updateActive'); - - $result = $this->Behavior->socialLogin($data, $options); - $this->assertEquals($result->id, '00000000-0000-0000-0000-000000000002'); - $this->assertTrue($result->active); - } - - /** - * Provider for socialLogin with facebook with existing and active user - * - */ - public function providerFacebookSocialLoginExistingReference() - { - return [ - 'provider' => [ - 'data' => [ - 'id' => 'reference-2-1', - 'provider' => 'Facebook' - ], - 'options' => [ - 'use_email' => true, - 'validate_email' => true, - 'token_expiration' => 3600 - ], - ] - - ]; - } - - /** - * Test socialLogin with existing and active user and not active social account - * - * @expectedException CakeDC\Users\Exception\AccountNotActiveException - * @dataProvider providerSocialLoginExistingAndNotActiveAccount - */ - public function testSocialLoginExistingNotActiveReference($data, $options) - { - $this->Behavior->expects($this->never()) - ->method('generateUniqueUsername'); - - $this->Behavior->expects($this->never()) - ->method('randomString'); - - $this->Behavior->expects($this->never()) - ->method('_updateActive'); - $this->Behavior->socialLogin($data, $options); - } - - /** - * Provider for socialLogin with existing and active user and not active social account - * - */ - public function providerSocialLoginExistingAndNotActiveAccount() - { - return [ - 'provider' => [ - 'data' => [ - 'id' => 'reference-1-1234', - 'provider' => 'Facebook' - ], - 'options' => [ - 'use_email' => true, - 'validate_email' => true, - 'token_expiration' => 3600 - ], - ] - - ]; - } - - /** - * Test socialLogin with existing and active account but not active user - * - * @expectedException CakeDC\Users\Exception\UserNotActiveException - * @dataProvider providerSocialLoginExistingAccountNotActiveUser - */ - public function testSocialLoginExistingReferenceNotActiveUser($data, $options) - { - $this->Behavior->expects($this->never()) - ->method('generateUniqueUsername'); - - $this->Behavior->expects($this->never()) - ->method('randomString'); - - $this->Behavior->expects($this->never()) - ->method('_updateActive'); - $this->Behavior->socialLogin($data, $options); - } - - /** - * Provider for socialLogin with existing and active account but not active user - * - */ - public function providerSocialLoginExistingAccountNotActiveUser() - { - return [ - 'provider' => [ - 'data' => [ - 'id' => 'reference-1-1234', - 'provider' => 'Twitter' - ], - 'options' => [ - 'use_email' => true, - 'validate_email' => true, - 'token_expiration' => 3600 - ], - ] - - ]; - } - - /** - * Test socialLogin with facebook and not existing user - * - * @dataProvider providerFacebookSocialLoginNoEmail - * @expectedException CakeDC\Users\Exception\MissingEmailException - */ - public function testSocialLoginNoEmail($data, $options) - { - $this->Behavior->socialLogin($data, $options); - } - - /** - * Provider for socialLogin with facebook and not existing user - * - */ - public function providerFacebookSocialLoginNoEmail() - { - return [ - 'provider' => [ - 'data' => [ - 'id' => 'facebook-id', - 'username' => null, - 'full_name' => 'Full name', - 'first_name' => 'First name', - 'last_name' => 'Last name', - 'validated' => true, - 'link' => 'facebook-link', - 'provider' => 'Facebook' - ], - 'options' => [ - 'use_email' => true, - 'validate_email' => true, - 'token_expiration' => 3600 - ], - ] - - ]; - } - - /** - * Test socialLogin with facebook and not existing user - * - * @dataProvider providerGenerateUsername - */ - public function testGenerateUniqueUsername($param, $expected) - { - $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialBehavior') - ->setMethods(['randomString', '_updateActive']) - ->setConstructorArgs([$this->Table]) - ->getMock(); - - $result = $this->Behavior->generateUniqueUsername($param); - $this->assertEquals($expected, $result); - } - - /** - * Provider for socialLogin with facebook and not existing user - * - */ - public function providerGenerateUsername() - { - return [ - ['username', 'username'], - ['user-1', 'user-10'], - ['user-5', 'user-50'] - - ]; - } -} diff --git a/tests/TestCase/Model/Entity/UserTest.php b/tests/TestCase/Model/Entity/UserTest.php deleted file mode 100644 index 03165a769..000000000 --- a/tests/TestCase/Model/Entity/UserTest.php +++ /dev/null @@ -1,206 +0,0 @@ -now = Time::now(); - Time::setTestNow($this->now); - $this->User = new User(); - } - - /** - * tearDown method - * - * @return void - */ - public function tearDown() - { - unset($this->User); - Time::setTestNow(); - - parent::tearDown(); - } - - /** - * Test tokenExpired method - * - * @return void - */ - public function testTokenExpiredEmpty() - { - $this->User->token_expires = null; - $isExpired = $this->User->tokenExpired(); - $this->assertTrue($isExpired); - } - - /** - * Test tokenExpired method - * - * @return void - */ - public function testTokenExpiredNotYet() - { - $this->User->token_expires = '-1 day'; - $isExpired = $this->User->tokenExpired(); - $this->assertTrue($isExpired); - } - - /** - * Test tokenExpired method - * - * @return void - */ - public function testTokenExpired() - { - $this->User->token_expires = '+1 day'; - $isExpired = $this->User->tokenExpired(); - $this->assertFalse($isExpired); - } - - /** - * Test tokenExpired another locale - * - * @return void - */ - public function testTokenExpiredLocale() - { - I18n::setLocale('es_AR'); - $this->User->token_expires = '+1 day'; - $isExpired = $this->User->tokenExpired(); - $this->assertFalse($isExpired); - $this->User->token_expires = '-1 day'; - $isExpired = $this->User->tokenExpired(); - $this->assertTrue($isExpired); - I18n::setLocale('en_US'); - } - - /** - * test - * - * @return void - */ - public function testPasswordsAreEncrypted() - { - $pw = 'password'; - $this->User->password = $pw; - $this->assertTrue((new DefaultPasswordHasher)->check($pw, $this->User->password)); - } - - public function testConfirmPasswordsAreEncrypted() - { - $pw = 'password'; - $this->User->confirm_password = $pw; - $this->assertTrue((new DefaultPasswordHasher)->check($pw, $this->User->confirm_password)); - } - - /** - * test - * - * @return void - */ - public function testCheckPassword() - { - $pw = 'password'; - $this->assertTrue($this->User->checkPassword($pw, (new DefaultPasswordHasher)->hash($pw))); - $this->assertFalse($this->User->checkPassword($pw, 'fail')); - } - - /** - * test - * - * @return void - */ - public function testGetAvatar() - { - $this->assertNull($this->User->avatar); - $avatar = 'first-avatar'; - $this->User->social_accounts = [ - ['avatar' => 'first-avatar'], - ['avatar' => 'second-avatar'] - ]; - $this->assertSame($avatar, $this->User->avatar); - } - - /** - * test - * - * @return void - */ - public function testUpdateToken() - { - $this->assertNull($this->User['token']); - $this->assertNull($this->User['token_expires']); - $this->User->updateToken(); - $this->assertEquals($this->now, $this->User['token_expires']); - $this->assertNotNull($this->User['token']); - } - - /** - * test - * - * @return void - */ - public function testUpdateTokenExisting() - { - $this->User['token'] = 'aaa'; - $this->User['token_expires'] = $this->now; - $this->User->updateToken(); - $this->assertEquals($this->now, $this->User['token_expires']); - $this->assertNotEquals('aaa', $this->User['token']); - } - - /** - * test - * - * @return void - */ - public function testUpdateTokenAdd() - { - $this->assertNull($this->User['token']); - $this->assertNull($this->User['token_expires']); - $this->User->updateToken(20); - $this->assertEquals('20 seconds after', $this->User['token_expires']->diffForHumans($this->now)); - $this->assertNotNull($this->User['token']); - } - - /** - * test - * - * @return void - */ - public function testUpdateTokenExistingAdd() - { - $this->User['token'] = 'aaa'; - $this->User['token_expires'] = $this->now; - $this->User->updateToken(20); - $this->assertEquals('20 seconds after', $this->User['token_expires']->diffForHumans($this->now)); - $this->assertNotEquals('aaa', $this->User['token']); - } -} diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php deleted file mode 100644 index f662d7bf2..000000000 --- a/tests/TestCase/Model/Table/SocialAccountsTableTest.php +++ /dev/null @@ -1,74 +0,0 @@ -SocialAccounts = TableRegistry::getTableLocator()->get('CakeDC/Users.SocialAccounts'); - } - - /** - * tearDown method - * - * @return void - */ - public function tearDown() - { - unset($this->SocialAccounts); - - parent::tearDown(); - } - - public function testValidationHappy() - { - $data = [ - 'provider' => 'Facebook', - 'reference' => 'test-reference', - 'link' => 'test-link', - 'token' => 'test-token', - 'active' => 0, - 'data' => 'test-data', - ]; - $entity = $this->SocialAccounts->newEntity($data); - $this->assertEmpty($entity->getErrors()); - } -} diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php deleted file mode 100644 index 03b91b37e..000000000 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ /dev/null @@ -1,312 +0,0 @@ -Users = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $this->fullBaseBackup = Router::fullBaseUrl(); - Router::fullBaseUrl('http://users.test'); - Email::setConfigTransport('test', [ - 'className' => 'Debug' - ]); - Email::setConfig('default', [ - 'transport' => 'test', - 'from' => 'cakedc@example.com' - ]); - } - - /** - * tearDown method - * - * @return void - */ - public function tearDown() - { - unset($this->Users); - Router::fullBaseUrl($this->fullBaseBackup); - Email::drop('default'); - Email::dropTransport('test'); - - parent::tearDown(); - } - - /** - * Test register method - * - * @return void - */ - public function testValidateRegisterNoValidateEmail() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - 'tos' => 1 - ]; - $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 0]); - $this->assertTrue($result->active); - } - - /** - * Test register method - * - * @return void - */ - public function testValidateRegisterEmptyUser() - { - $user = []; - $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); - $this->assertFalse($result); - } - - /** - * Test register method - * - * @return void - */ - public function testValidateRegisterValidateEmail() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - 'tos' => 1 - ]; - $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); - $this->assertNotEmpty($result); - $this->assertFalse($result->active); - } - - /** - * test - */ - public function testValidateRegisterTosRequired() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - ]; - $userEntity = $this->Users->newEntity(); - $this->Users->register($userEntity, $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); - $this->assertEquals(['tos' => ['_required' => 'This field is required']], $userEntity->getErrors()); - } - - /** - * Test register method - * testValidateRegisterValidateEmail - */ - public function testValidateRegisterNoTosRequired() - { - $user = [ - 'username' => 'testuser', - 'email' => 'testuser@test.com', - 'password' => 'password', - 'password_confirm' => 'password', - 'first_name' => 'test', - 'last_name' => 'user', - ]; - $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); - $this->assertNotEmpty($result); - } - - /** - * Test ActivateUser method - * - * @return void - */ - public function testActivateUser() - { - $user = $this->Users->find()->where(['id' => '00000000-0000-0000-0000-000000000001'])->first(); - $result = $this->Users->activateUser($user); - $this->assertTrue($result->active); - } - - public function testSocialLogin() - { - $data = [ - 'provider' => SocialAccountsTable::PROVIDER_FACEBOOK, - 'email' => 'user-2@test.com', - 'id' => 'reference-2-1', - 'link' => 'link', - 'raw' => [ - 'id' => 'reference-2-1', - 'token' => 'token', - 'first_name' => 'User 2', - 'gender' => 'female', - 'verified' => 1, - 'user_email' => 'user-2@test.com', - 'link' => 'link' - ] - ]; - $options = [ - 'use_email' => 1, - 'validate_email' => 1, - 'token_expiration' => 3600 - ]; - $result = $this->Users->socialLogin($data, $options); - $this->assertEquals('user-2@test.com', $result->email); - $this->assertTrue($result->active); - } - - /** - * Test socialLogin - * - * @expectedException CakeDC\Users\Exception\AccountNotActiveException - */ - public function testSocialLoginInactiveAccount() - { - $data = [ - 'provider' => SocialAccountsTable::PROVIDER_TWITTER, - 'email' => 'hello@test.com', - 'id' => 'reference-2-2', - 'link' => 'link', - 'raw' => [ - 'id' => 'reference-2-2', - 'first_name' => 'User 2', - 'gender' => 'female', - 'verified' => 1, - 'user_email' => 'hello@test.com', - ] - ]; - $options = [ - 'use_email' => 1, - 'validate_email' => 1, - 'token_expiration' => 3600 - ]; - $result = $this->Users->socialLogin($data, $options); - $this->assertEquals('user-2@test.com', $result->email); - $this->assertFalse($result->active); - } - - /** - * Test socialLogin - * - * @expectedException InvalidArgumentException - */ - public function testSocialLoginCreateNewAccountWithNoCredentials() - { - $data = [ - 'provider' => SocialAccountsTable::PROVIDER_TWITTER, - 'email' => 'user@test.com', - 'id' => 'reference-not-existing', - 'link' => 'link', - 'raw' => [ - 'id' => 'reference-not-existing', - 'first_name' => 'Not existing user', - 'gender' => 'male', - 'user_email' => 'user@test.com', - ], - 'credentials' => [], - 'name' => '', - ]; - - $options = [ - 'use_email' => 0, - 'validate_email' => 1, - 'token_expiration' => 3600 - ]; - $result = $this->Users->socialLogin($data, $options); - $this->assertFalse($result); - } - - /** - * Test socialLogin - * - */ - public function testSocialLoginCreateNewAccount() - { - $data = [ - 'provider' => SocialAccountsTable::PROVIDER_TWITTER, - 'email' => 'username@test.com', - 'id' => 'no-existing-reference', - 'link' => 'link', - 'first_name' => 'First Name', - 'last_name' => 'Last Name', - 'raw' => [ - 'id' => 'no-existing-reference', - 'first_name' => 'First Name', - 'last_name' => 'Last Name', - 'gender' => 'male', - 'user_email' => 'user@test.com', - 'twitter' => 'link' - ], - 'info' => [ - 'first_name' => 'First Name', - 'last_name' => 'Last Name', - 'urls' => ['twitter' => 'twitter'] - ], - 'validated' => true, - 'credentials' => [ - 'token' => 'token', - 'token_secret' => 'secret', - 'token_expires' => '' - ], - ]; - - $options = [ - 'use_email' => 0, - 'validate_email' => 0, - 'token_expiration' => 3600 - ]; - $result = $this->Users->socialLogin($data, $options); - $this->assertNotEmpty($result); - $this->assertEquals('no-existing-reference', $result->social_accounts[0]->reference); - $this->assertEquals(1, count($result->social_accounts)); - $this->assertEquals('username', $result->username); - $this->assertEquals('First Name', $result->first_name); - $this->assertEquals('Last Name', $result->last_name); - } -} diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php deleted file mode 100644 index 05bd3e58f..000000000 --- a/tests/TestCase/Shell/UsersShellTest.php +++ /dev/null @@ -1,418 +0,0 @@ -out = new ConsoleOutput(); - $this->io = $this->getMockBuilder('Cake\Console\ConsoleIo')->getMock(); - $this->Users = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - - $this->Shell = $this->getMockBuilder('CakeDC\Users\Shell\UsersShell') - ->setMethods(['in', 'out', '_stop', 'clear', '_usernameSeed', '_generateRandomPassword', - '_generateRandomUsername', '_generatedHashedPassword', 'error', '_updateUser']) - ->setConstructorArgs([$this->io]) - ->getMock(); - - $this->Shell->Users = $this->getMockBuilder('CakeDC\Users\Model\Table\UsersTable') - ->setMethods(['generateUniqueUsername', 'newEntity', 'save', 'updateAll']) - ->getMock(); - - $this->Shell->Command = $this->getMockBuilder('Cake\Shell\Task\CommandTask') - ->setMethods(['in', '_stop', 'clear', 'out']) - ->setConstructorArgs([$this->io]) - ->getMock(); - } - - /** - * Tear Down - * - * @return void - */ - public function tearDown() - { - parent::tearDown(); - unset($this->Shell); - } - - /** - * Add user test - * Adding user with username, email, password and role - * - * @return void - */ - public function testAddUser() - { - $user = [ - 'username' => 'yeliparra', - 'password' => '123', - 'email' => 'yeli.parra@example.com', - 'active' => 1, - ]; - $role = 'tester'; - - $this->Shell->expects($this->never()) - ->method('_generateRandomUsername'); - - $this->Shell->expects($this->never()) - ->method('_generateRandomPassword'); - - $this->Shell->Users->expects($this->once()) - ->method('generateUniqueUsername') - ->with($user['username']) - ->will($this->returnValue($user['username'])); - - $entityUser = $this->Users->newEntity($user); - $entityUser->role = $role; - - $this->Shell->Users->expects($this->once()) - ->method('newEntity') - ->with($user) - ->will($this->returnValue($entityUser)); - - $userSaved = $entityUser; - $userSaved->id = 'my-id'; - - $this->Shell->Users->expects($this->once()) - ->method('save') - ->with($entityUser) - ->will($this->returnValue($userSaved)); - - $this->Shell->runCommand(['addUser', '--username=' . $user['username'], '--password=' . $user['password'], '--email=' . $user['email'], '--role=' . $role]); - } - - /** - * Add user test - * Adding user passing no params - * - * @return void - */ - public function testAddUserWithNoParams() - { - $user = [ - 'username' => 'anakin', - 'password' => 'mypassword', - 'email' => 'anakin@example.com', - 'active' => 1, - ]; - - $this->Shell->Users->expects($this->once()) - ->method('generateUniqueUsername') - ->with($user['username']) - ->will($this->returnValue($user['username'])); - - $this->Shell->expects($this->once()) - ->method('_generateRandomPassword') - ->will($this->returnValue($user['password'])); - - $this->Shell->expects($this->once()) - ->method('_generateRandomUsername') - ->will($this->returnValue($user['username'])); - - $entityUser = $this->Users->newEntity($user); - $entityUser->role = 'user'; - - $this->Shell->Users->expects($this->once()) - ->method('newEntity') - ->with($user) - ->will($this->returnValue($entityUser)); - - $userSaved = $entityUser; - $userSaved->id = 'my-id'; - - $this->Shell->Users->expects($this->once()) - ->method('save') - ->with($entityUser) - ->will($this->returnValue($userSaved)); - - //TODO: Add assertions with 'out' - - $this->Shell->runCommand(['addUser']); - } - - /** - * Add user test - * Adding user with username, email, password and role - * - * @return void - */ - public function testAddSuperuser() - { - $user = [ - 'username' => 'yeliparra', - 'password' => '123', - 'email' => 'yeli.parra@example.com', - 'active' => 1, - ]; - $role = 'tester'; - - $this->Shell->expects($this->never()) - ->method('_generateRandomUsername'); - - $this->Shell->expects($this->never()) - ->method('_generateRandomPassword'); - - $this->Shell->Users->expects($this->once()) - ->method('generateUniqueUsername') - ->with($user['username']) - ->will($this->returnValue($user['username'])); - - $entityUser = $this->Users->newEntity($user); - $entityUser->role = $role; - - $this->Shell->Users->expects($this->once()) - ->method('newEntity') - ->with($user) - ->will($this->returnValue($entityUser)); - - $userSaved = $entityUser; - $userSaved->id = 'my-id'; - $userSaved->is_superuser = true; - - $this->Shell->Users->expects($this->once()) - ->method('save') - ->with($entityUser) - ->will($this->returnValue($userSaved)); - - $this->Shell->runCommand(['addSuperuser', '--username=' . $user['username'], '--password=' . $user['password'], '--email=' . $user['email'], '--role=' . $role]); - } - - /** - * Add superadmin user - * - * @return void - */ - public function testAddSuperuserWithNoParams() - { - $this->Shell->Users->expects($this->once()) - ->method('generateUniqueUsername') - ->with('superadmin') - ->will($this->returnValue('superadmin')); - - $this->Shell->expects($this->once()) - ->method('_generateRandomPassword') - ->will($this->returnValue('password')); - - $user = [ - 'username' => 'superadmin', - 'password' => 'password', - 'email' => 'superadmin@example.com', - 'active' => 1, - ]; - $entityUser = $this->Users->newEntity($user); - - $this->Shell->Users->expects($this->once()) - ->method('newEntity') - ->with($user) - ->will($this->returnValue($entityUser)); - - $userSaved = $entityUser; - $userSaved->id = 'my-id'; - $userSaved->is_superuser = true; - $userSaved->role = 'superuser'; - - $this->Shell->Users->expects($this->once()) - ->method('save') - ->with($entityUser) - ->will($this->returnValue($userSaved)); - - $this->Shell->runCommand(['addSuperuser']); - } - - /** - * Reset all passwords - * - * @return void - */ - public function testResetAllPasswords() - { - $this->Shell->expects($this->once()) - ->method('_generatedHashedPassword') - ->will($this->returnValue('hashedPasssword')); - - $this->Shell->Users->expects($this->once()) - ->method('updateAll') - ->with(['password' => 'hashedPasssword'], ['id IS NOT NULL']); - - $this->Shell->runCommand(['resetAllPasswords', '123']); - } - - /** - * Reset all passwords - * - * @expectedException \Cake\Console\Exception\StopException - * @expectedExceptionMessage Please enter a password. - */ - public function testResetAllPasswordsNoPassingParams() - { - $this->Shell->runCommand(['resetAllPasswords']); - } - - /** - * Reset password - * - * @return void - */ - public function testResetPassword() - { - $user = $this->Users->newEntity(); - $user->username = 'user-1'; - $user->password = 'password'; - - $this->Shell->expects($this->once()) - ->method('_updateUser') - ->will($this->returnValue($user)); - - $this->Shell->runCommand(['resetPassword', 'user-1', 'password']); - } - - /** - * Change role - * - * @return void - */ - public function testChangeRole() - { - $this->Shell = new UsersShell($this->io); - $this->Shell->Users = $this->Users; - $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); - $this->assertSame('admin', $user['role']); - $this->Shell->runCommand(['changeRole', 'user-1', 'another-role']); - $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); - $this->assertSame('another-role', $user['role']); - } - - /** - * Activate user - * - * @return void - */ - public function testActivateUser() - { - $this->Shell = new UsersShell($this->io); - $this->Shell->Users = $this->Users; - $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); - $this->assertFalse($user['active']); - $this->Shell->runCommand(['activateUser', 'user-1']); - $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); - $this->assertTrue($user['active']); - } - - /** - * Delete user - * - * @return void - * @expected - */ - public function testDeleteUser() - { - $this->Shell = new UsersShell($this->io); - $this->Shell->Users = $this->Users; - - $this->assertNotEmpty($this->Users->findById('00000000-0000-0000-0000-000000000001')->first()); - $this->assertNotEmpty($this->Users->SocialAccounts->findByUserId('00000000-0000-0000-0000-000000000001')->toArray()); - $this->Shell->runCommand(['deleteUser', 'user-1']); - $this->assertEmpty($this->Users->findById('00000000-0000-0000-0000-000000000001')->first()); - $this->assertEmpty($this->Users->SocialAccounts->findByUserId('00000000-0000-0000-0000-000000000001')->toArray()); - - $this->assertNotEmpty($this->Users->findById('00000000-0000-0000-0000-000000000005')->first()); - $this->Shell->runCommand(['deleteUser', 'user-5']); - $this->assertEmpty($this->Users->findById('00000000-0000-0000-0000-000000000005')->first()); - } - - /** - * test - * - * @return void - */ - public function testAddUserCustomRole() - { - $this->Shell = new UsersShell($this->io); - $this->Shell->Users = $this->Users; - $this->assertEmpty($this->Users->findByUsername('custom')->first()); - $this->Shell->runCommand([ - 'addUser', - '--username=custom', - '--password=12345678', - '--email=custom@example.com', - '--role=custom' - ]); - $user = $this->Users->findByUsername('custom')->first(); - $this->assertSame('custom', $user['role']); - } - - /** - * test - * - * @return void - */ - public function testAddUserDefaultRole() - { - $this->Shell = new UsersShell($this->io); - $this->Shell->Users = $this->Users; - $this->assertEmpty($this->Users->findByUsername('custom')->first()); - Configure::write('Users.Registration.defaultRole', false); - $this->Shell->runCommand([ - 'addUser', - '--username=custom', - '--password=12345678', - '--email=custom@example.com', - ]); - $user = $this->Users->findByUsername('custom')->first(); - $this->assertSame('user', $user['role']); - } - - /** - * test - * - * @return void - */ - public function testAddUserCustomDefaultRole() - { - $this->Shell = new UsersShell($this->io); - $this->Shell->Users = $this->Users; - $this->assertEmpty($this->Users->findByUsername('custom')->first()); - Configure::write('Users.Registration.defaultRole', 'emperor'); - $this->Shell->runCommand([ - 'addUser', - '--username=custom', - '--password=12345678', - '--email=custom@example.com', - ]); - $user = $this->Users->findByUsername('custom')->first(); - $this->assertSame('emperor', $user['role']); - } -} diff --git a/tests/TestCase/Traits/RandomStringTraitTest.php b/tests/TestCase/Traits/RandomStringTraitTest.php deleted file mode 100644 index f1411a44a..000000000 --- a/tests/TestCase/Traits/RandomStringTraitTest.php +++ /dev/null @@ -1,43 +0,0 @@ -Trait = $this->getMockForTrait('CakeDC\Users\Traits\RandomStringTrait'); - } - - public function tearDown() - { - parent::tearDown(); - } - - public function testRandomString() - { - $result = $this->Trait->randomString(); - $this->assertEquals(10, strlen($result)); - - $result = $this->Trait->randomString(30); - $this->assertEquals(30, strlen($result)); - - $result = $this->Trait->randomString('-300'); - $this->assertEquals(10, strlen($result)); - - $result = $this->Trait->randomString('text'); - $this->assertEquals(10, strlen($result)); - } -} diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php deleted file mode 100644 index 3817c10ef..000000000 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ /dev/null @@ -1,156 +0,0 @@ -AuthLink = new AuthLinkHelper($view); - } - - /** - * tearDown method - * - * @return void - */ - public function tearDown() - { - unset($this->AuthLink); - - parent::tearDown(); - } - - /** - * Test link - * - * @return void - */ - public function testLinkFalse() - { - $link = $this->AuthLink->link('title', ['controller' => 'noaccess']); - $this->assertSame(false, $link); - } - - /** - * Test link - * - * @return void - */ - public function testLinkAuthorized() - { - $view = new View(); - $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') - ->setMethods(['dispatch']) - ->getMock(); - EventManager::instance($eventManagerMock); - $this->AuthLink = new AuthLinkHelper($view); - $result = new Event('dispatch-result'); - $result->result = true; - $eventManagerMock->expects($this->once()) - ->method('dispatch') - ->will($this->returnValue($result)); - - $link = $this->AuthLink->link('title', '/', ['before' => 'before_', 'after' => '_after', 'class' => 'link-class']); - $this->assertSame('before_title_after', $link); - } - - /** - * Test link - * - * @return void - */ - public function testLinkAuthorizedAllowedTrue() - { - $view = new View(); - $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') - ->setMethods(['dispatch']) - ->getMock(); - EventManager::instance($eventManagerMock); - $this->AuthLink = new AuthLinkHelper($view); - $result = new Event('dispatch-result'); - $result->result = true; - $eventManagerMock->expects($this->never()) - ->method('dispatch'); - - $link = $this->AuthLink->link('title', '/', ['allowed' => true, 'before' => 'before_', 'after' => '_after', 'class' => 'link-class']); - $this->assertSame('before_title_after', $link); - } - - /** - * Test link - * - * @return void - */ - public function testLinkAuthorizedAllowedFalse() - { - $view = new View(); - $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') - ->setMethods(['dispatch']) - ->getMock(); - $view->getEventManager($eventManagerMock); - $this->AuthLink = new AuthLinkHelper($view); - $result = new Event('dispatch-result'); - $eventManagerMock->expects($this->never()) - ->method('dispatch'); - $link = $this->AuthLink->link('title', '/', ['allowed' => false, 'before' => 'before_', 'after' => '_after', 'class' => 'link-class']); - $this->assertFalse($link); - } - - /** - * Test isAuthorized - * - * @return void - */ - public function testIsAuthorized() - { - $view = new View(); - $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') - ->setMethods(['dispatch']) - ->getMock(); - EventManager::instance($eventManagerMock); - $this->AuthLink = new AuthLinkHelper($view); - $result = new Event('dispatch-result'); - $result->result = true; - $eventManagerMock->expects($this->once()) - ->method('dispatch') - ->will($this->returnValue($result)); - - $result = $this->AuthLink->isAuthorized(['controller' => 'MyController', 'action' => 'myAction']); - $this->assertTrue($result); - } -} diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php deleted file mode 100644 index 3fafbb9bf..000000000 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ /dev/null @@ -1,380 +0,0 @@ -oauthConfig === null) { - $this->oauthConfig = (array)Configure::read('OAuth'); - $this->socialLogin = Configure::read('Users.Social.login'); - } - - parent::setUp(); - $this->View = $this->getMockBuilder('Cake\View\View') - ->setMethods(['append']) - ->getMock(); - //Assuming all these url's are authorized - $this->AuthLink = $this->getMockBuilder('CakeDC\Users\View\Helper\AuthLinkHelper') - ->setMethods(['isAuthorized']) - ->setConstructorArgs([$this->View]) - ->getMock(); - $this->AuthLink->expects($this->any()) - ->method('isAuthorized') - ->will($this->returnValue(true)); - $this->User = new UserHelper($this->View); - $this->User->AuthLink = $this->AuthLink; - $this->request = new ServerRequest(); - } - - /** - * tearDown method - * - * @return void - */ - public function tearDown() - { - Configure::write('OAuth', $this->oauthConfig); - Configure::write('Users.Social.login', $this->socialLogin); - unset($this->User); - - parent::tearDown(); - } - - /** - * Test twitterLogin - * - * @return void - */ - public function testLogout() - { - $result = $this->User->logout(); - $expected = 'Logout'; - $this->assertEquals($expected, $result); - } - - /** - * Test twitterLogin - * - * @return void - */ - public function testLogoutDifferentMessage() - { - $result = $this->User->logout('Sign Out'); - $expected = 'Sign Out'; - $this->assertEquals($expected, $result); - } - - /** - * Test twitterLogin - * - * @return void - */ - public function testLogoutWithOptions() - { - $result = $this->User->logout('Sign Out', ['class' => 'logout']); - $expected = 'Sign Out'; - $this->assertEquals($expected, $result); - } - - /** - * Test link - * - * @return void - */ - public function testWelcome() - { - $session = $this->getMockBuilder('Cake\Http\Session') - ->setMethods(['read']) - ->getMock(); - $session->expects($this->at(0)) - ->method('read') - ->with('Auth.User.id') - ->will($this->returnValue(2)); - - $session->expects($this->at(1)) - ->method('read') - ->with('Auth.User.first_name') - ->will($this->returnValue('david')); - - $this->User->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['getSession']) - ->getMock(); - $this->User->request->expects($this->any()) - ->method('getSession') - ->will($this->returnValue($session)); - - $expected = 'Welcome, david'; - $result = $this->User->welcome(); - $this->assertEquals($expected, $result); - } - - /** - * Test link - * - * @return void - */ - public function testWelcomeNotLoggedInUser() - { - $session = $this->getMockBuilder('Cake\Http\Session') - ->setMethods(['read']) - ->getMock(); - $session->expects($this->at(0)) - ->method('read') - ->with('Auth.User.id') - ->will($this->returnValue(null)); - - $this->User->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['getSession']) - ->getMock(); - $this->User->request->expects($this->any()) - ->method('getSession') - ->will($this->returnValue($session)); - - $result = $this->User->welcome(); - $this->assertEmpty($result); - } - - /** - * Test add ReCaptcha field - * - * @return void - */ - public function testAddReCaptcha() - { - Configure::write('Users.reCaptcha.key', 'testKey'); - Configure::write('Users.reCaptcha.theme', 'light'); - Configure::write('Users.reCaptcha.size', 'normal'); - Configure::write('Users.reCaptcha.tabindex', '3'); - $result = $this->User->addReCaptcha(); - $this->assertEquals('
', $result); - } - - /** - * Test add ReCaptcha field - * - * @return void - */ - public function testAddReCaptchaEmpty() - { - $result = $this->User->addReCaptcha(); - $expected = '

reCaptcha is not configured! Please configure Users.reCaptcha.key

'; - $this->assertEquals($expected, $result); - } - - /** - * Test add ReCaptcha field - * - * @return void - */ - public function testAddReCaptchaScript() - { - $this->View->expects($this->at(0)) - ->method('append') - ->with('script', $this->stringContains('https://www.google.com/recaptcha/api.js')); - $this->User->addReCaptchaScript(); - } - - /** - * Test social login link - * - * @return void - */ - public function testSocialLoginLink() - { - $result = $this->User->socialLogin('facebook'); - $this->assertEquals('Sign in with Facebook', $result); - - $result = $this->User->socialLogin('twitter', ['label' => 'Register with']); - $this->assertEquals('Register with Twitter', $result); - } - - /** - * test - * - * @return void - */ - public function testSocialLoginTranslation() - { - I18n::setLocale('es_ES'); - $result = $this->User->socialLogin('facebook'); - $this->assertEquals('Iniciar sesiĆ³n con Facebook', $result); - I18n::setLocale('en_US'); - } - - /** - * Test social connect link list - * - * @return void - */ - public function testSocialConnectLinkList() - { - Configure::write('Users.Social.login', true); - - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - - Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); - Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); - - $actual = $this->User->socialConnectLinkList(); - $expected = ' Connect with Facebook'; - $expected .= ' Connect with Google'; - $this->assertEquals($expected, $actual); - } - - /** - * Test social connect link list, user is connected with facebook - * - * @return void - */ - public function testSocialConnectLinkListIsConnectedWithFacebook() - { - Configure::write('Users.Social.login', true); - - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - - Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); - Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); - - $socialAccounts = [ - new SocialAccount([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'user_id' => '00000000-0000-0000-0000-000000000001', - 'provider' => 'Facebook', - 'username' => 'user-1-fb', - 'reference' => 'reference-1-1234', - 'avatar' => 'Lorem ipsum dolor sit amet', - 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', - 'token' => 'token-1234', - 'token_secret' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-05-22 21:52:44', - 'active' => false, - 'data' => '', - 'created' => '2015-05-22 21:52:44', - 'modified' => '2015-05-22 21:52:44' - ]) - ]; - $actual = $this->User->socialConnectLinkList($socialAccounts); - $expected = ' Connected with Facebook'; - $expected .= ' Connect with Google'; - $this->assertEquals($expected, $actual); - } - - /** - * Test social connect link list, social is not enabled - * - * @return void - */ - public function testSocialConnectLinkListSocialIsNotEnabled() - { - Configure::write('Users.Social.login', false); - - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - - Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); - Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); - - $socialAccounts = [ - new SocialAccount([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'user_id' => '00000000-0000-0000-0000-000000000001', - 'provider' => 'Facebook', - 'username' => 'user-1-fb', - 'reference' => 'reference-1-1234', - 'avatar' => 'Lorem ipsum dolor sit amet', - 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', - 'token' => 'token-1234', - 'token_secret' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-05-22 21:52:44', - 'active' => false, - 'data' => '', - 'created' => '2015-05-22 21:52:44', - 'modified' => '2015-05-22 21:52:44' - ]) - ]; - $actual = $this->User->socialConnectLinkList($socialAccounts); - $expected = ''; - $this->assertEquals($expected, $actual); - } - - /** - * Test social connect link list, social is enabled but any provider was configured - * - * @return void - */ - public function testSocialConnectLinkListSocialEnabledButNotConfiguredProvider() - { - Configure::write('Users.Social.login', true); - - $socialAccounts = [ - new SocialAccount([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'user_id' => '00000000-0000-0000-0000-000000000001', - 'provider' => 'Facebook', - 'username' => 'user-1-fb', - 'reference' => 'reference-1-1234', - 'avatar' => 'Lorem ipsum dolor sit amet', - 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', - 'token' => 'token-1234', - 'token_secret' => 'Lorem ipsum dolor sit amet', - 'token_expires' => '2015-05-22 21:52:44', - 'active' => false, - 'data' => '', - 'created' => '2015-05-22 21:52:44', - 'modified' => '2015-05-22 21:52:44' - ]) - ]; - $actual = $this->User->socialConnectLinkList($socialAccounts); - $expected = ''; - $this->assertEquals($expected, $actual); - } -} diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index e94978c62..000000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,130 +0,0 @@ - 'Users\Test\App']); - -Cake\Core\Configure::write('debug', true); -Cake\Core\Configure::write('App.encoding', 'UTF-8'); - -ini_set('intl.default_locale', 'en_US'); - -$TMP = new \Cake\Filesystem\Folder(TMP); -$TMP->create(TMP . 'cache/models', 0777); -$TMP->create(TMP . 'cache/persistent', 0777); -$TMP->create(TMP . 'cache/views', 0777); - -$cache = [ - 'default' => [ - 'engine' => 'File', - ], - '_cake_core_' => [ - 'className' => 'File', - 'prefix' => 'users_myapp_cake_core_', - 'path' => CACHE . 'persistent/', - 'serialize' => true, - 'duration' => '+10 seconds', - ], - '_cake_model_' => [ - 'className' => 'File', - 'prefix' => 'users_app_cake_model_', - 'path' => CACHE . 'models/', - 'serialize' => 'File', - 'duration' => '+10 seconds', - ], -]; - -Cake\Cache\Cache::setConfig($cache); -Cake\Core\Configure::write('Session', [ - 'defaults' => 'php' -]); - -//init router -\Cake\Routing\Router::reload(); - -\Cake\Core\Plugin::load('CakeDC/Users', [ - 'path' => dirname(dirname(__FILE__)) . DS, - 'routes' => true -]); -if (file_exists($root . '/config/bootstrap.php')) { - require $root . '/config/bootstrap.php'; -} - -Cake\Routing\DispatcherFactory::add('Routing'); -Cake\Routing\DispatcherFactory::add('ControllerFactory'); - -class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\AppController'); - -// Ensure default test connection is defined -if (!getenv('db_dsn')) { - putenv('db_dsn=sqlite:///:memory:'); -} - -Cake\Datasource\ConnectionManager::setConfig('test', [ - 'url' => getenv('db_dsn'), -// 'className' => 'Cake\Database\Connection', -// 'driver' => 'Cake\Database\Driver\Postgres', -// 'persistent' => true, -// 'host' => 'localhost', -// 'username' => 'my_app', -// 'password' => null, -// 'database' => 'test', -// 'schema' => 'public', -// 'port' => 5432, -// 'encoding' => 'utf8', -// 'flags' => [], -// 'init' => [], - 'timezone' => 'UTC' -]); - -\Cake\Core\Configure::write('App.paths.templates', [ - APP . 'Template/', -]); diff --git a/tests/config/routes.php b/tests/config/routes.php deleted file mode 100644 index 911b3c38b..000000000 --- a/tests/config/routes.php +++ /dev/null @@ -1,35 +0,0 @@ - '/users'], function ($routes) { - $routes->fallbacks('DashedRoute'); -}); - -$oauthPath = Configure::read('Opauth.path'); -if (is_array($oauthPath)) { - Router::scope('/auth', function ($routes) use ($oauthPath) { - $routes->connect( - '/*', - $oauthPath - ); - }); -} -Router::connect('/accounts/validate/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'SocialAccounts', - 'action' => 'validate' -]); -Router::connect('/profile/*', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); -Router::connect('/login', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); -Router::connect('/logout', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout']); diff --git a/webroot/empty b/webroot/empty deleted file mode 100644 index e69de29bb..000000000 diff --git a/webroot/img/avatar_placeholder.png b/webroot/img/avatar_placeholder.png deleted file mode 100644 index 5a29e1a2db3f5977b3f36c5ca633d9608db66288..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4015 zcmXAsc{J2(7{}cTLe^9mKN`ES59wy#3M0b|)%yd$9v9mzTfY8&U4=PkN5ec+E|BzQ4ej_m$u{k~u!a*yFH1Tg+Es_d2+|g#YxF`f+Sz%R)#6p%ZX8bWg1qb0wZ;`q2%7&$E9CTJKnC5Sv|abh@|Aj%43YMQb+5Q5Swqf<7gbi{eDj`IUSQ6g=WOspr$8gzbJ z^AVhsD0|m-6EeLnU!xSA1-pi#lAQZ^c4;1~M#~*`3Bx)=uhnYg7MAV9AT}r$)E`)Y zGvkltPCL&>an-Fkj)&hD#sTA$!3*d43=b{vy1CSdfkS)?In+f9GM;!+%L1A@U*ERt z2@UuW*1$Sf*tM!Ex0wO?%Hw~BZgpBZV zO2g^HlVo0K%{u~(XLejlWy}Jp{?2`%o;I<)ZuwkIWi#MNFjp%=!cH_8{dQ(sLq(Xo zxjo{_0~K0|iCdA$<;i?pt{_|f4DSXc>Ck+J@6V;YrhtnPw)oNZ1#2MYlJ5LeB&Vgw zND4b5!U946PLFmuZg6ek_)Fp|8xDeiRp@sCk1kWU`*I2qEo=4KuRMph6%wciy<6gH z4@;EUaYlQX*O1Qug^C%jC6r7}TdcTFHFTi_L84mU8GI{1J<(LNzSr1yT& zIb@8y&qYL=G@rU~&uqBkNOq73{TUqUuP(M?@#&;iLjGh9SJC>ZYXqyKNeUasoRewF z1~Q-SIWX=#JTWEm=w)wgZ4=@|IeCXW=2$ySo)$^mX`X54skYznaAiJ*Tg4pnE=0`q z2KihU{cc^BK01vknv$fSD}H1?nw6cnbo>2y#hovMweWrSmtpc@fYmC;<=`ZFt0%}C z2v^OIroqMIxjxHoMq^=bso2ra!!~)3EJi8z3Cl;GGP6Xr`xnhZL)es>zpBVlUGbS%=~ zC|cn6DYNTx(czXT1zJ)wJAb;(aO=csX%;iX6ki%4F|vG5-?vitZtMl4`?y#w?F&ZJ z51SBkN14JAAjj9l_N2F;)Lg`(2Qo_xQ6p8xq}Y?^938-s`Pc?v-sC z?Dbs+H0dxGW^#=$truRFS8@NBE|BFS_i|ld<_5 z(5&B5TZ#gFi$$J0TXT0_r5FHVZ0s6hw^y&7b+!X;?Y(37qHH})QOH7P(4U0ru;mPHpW zVnnJ6urwajW>3Z|Qh#+4;&L9F&Dzi#Cm8RTDSi8puHBj0y7yk%pX_YNWpV04Z1UI7 zd-aXURnQn?1wnb1>C8vpE$;p-1?RaKYLswTr6%!woKE~3a6U>ae4JBdj8i<#{ z@|C|bc!K0i7+f9px2}{}Y2=QDcOTtI;yyESO_^x+diI&Gm(+XVm2)OTn}ofM1Y#_0n9k!j~XHl8^j&HOWR(`TtJ3u_s=X!$oq9?g5DyfG!Rjs40` z%pf{-Cf27;`vq}a523foAO4&ex)Km$5Tz12KiEQ1X)2%S+^gvAXdu2|pXgfjw06pY zps4!oeXlIu(ewrZa z_o)@_fUfoHE4ytc)P(Ch_i@%tB8Bs&ME1n?&Cr7U-zEikCu@OqLE&w2Z86o%O}|~@ zbJO4_k`vKq_6%Ck1BdP)Y&Jzy%@J|wA5q_KF&*Pp;tKlaThL?a;fdG#be0Y^vTj$v zmv;7L_z?*_a#ZK5znOF5h|T5CEwh1QOyQxzqicTIm$6PHmSd2m4)K(J5w+HQwxoBrTwx3e)$OeZRcu4`2lm*-?)QCe^-Op?+yPI8GoRCl z4zh30cdDTB6q+1;yb{W)?x94=DCG`{Yx12h_IR2|dqL#Cz{yz0-rOda{IfsynlNuZ z-lxNCaWuJ~3ud&p@>Os^V{tLLuw+XcyX z_+tSy&Jz3}*LknxklBuPzLGds{ehSX?{{Ee41VhyV1drurxZ?U9z~V~N;vJCQjKUpN@YX76IQdn}6Kt$FIaeX=h))m9>lvU+RZ~p8 zl+nRv!g52^jY=ZOqQ6F@L4qSV=xvk(AEoO*AX6MANfZ+uWK8aQVP03b3ENo*>Dm(| zKb?zdE(SjY4;`y$q2$$M7LX}v3U_lcCi(CTXGfDE5DZ{lZ@|&#l5?Bf=`?-bAZ_FW zTt{QHGtz(li6>2{--RJ~W3rVjKs(=vDX0byw#4Iovgn3`3LiCSI0SkJ)Lf&}(q?%r z7|sri(@EhdBa*W(>tQ<>{;QNE{-Bu>&t0t~c4o-VKXAa6VQQ!V#OF6t(2Azb@7?g< z=pOf*DJHe2G$eqZYdAW88IE9E6_kN4ILMZC+t6_Ru8e-{WCKhexN=ZRwqV$+W-(W% zXheA7Gka;8L{2lsl)IGlq3^&nS+q2hlmJ4%s<1ka=24v2aE@Z$IKry=Q(QA;!S=8j z0}_SY3D0oG^vI(V+d+q(Qc~u@FbzL`OkS<0oQy(3QxBWVaIWDnp^5*7SVB=qu>y|! zCMmJpD*+^3YQ@h;SRxd5XfvEJ$;gTLs*E-mi%oEHF|EuXdDHh8*@Ne8v(SC?)!%pL&9jvX}7s7I?7G6n?$bmu7b!RN(=W&?Rn-cU4D z3myP4IQyv2oc>n6K2lK$M{ZrLr5%403vm;b=ChmRO8+4`8sg85Pk5CSGOofK%xHPygMlu zPp7DYY%Hcv6N- ztsj59irK^R??xM{IPD#3}KXtn+#iyoin8tglpIwVdH;gfdJzEOLxKu%rvb(gPcT% zPN01Lhs*Y0obpg;l7h+!6VzC7X5L)pzhs(Eo}uZXQfO;)wNb3~_`dNS$9o?$<^Lsd N^UK!8wU;~-{{ee?`}F_- From 1a0c21c7e6d34ee1ce062f6b6ba026044c4fbee9 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 20 Jan 2019 14:48:59 +0800 Subject: [PATCH 3/3] fork reset --- .semver | 5 + .travis.yml | 50 + CHANGELOG.md | 159 +++ CONTRIBUTING.md | 4 + Docs/Documentation/Configuration.md | 195 ++++ Docs/Documentation/Events.md | 60 ++ Docs/Documentation/Extending-the-Plugin.md | 219 +++++ .../Google-Two-Factor-Authenticator.md | 36 + .../Documentation/GoogleAuthenticator/App.png | Bin 0 -> 52261 bytes .../GoogleAuthenticator/FirstLogin.png | Bin 0 -> 21106 bytes Docs/Documentation/Installation.md | 115 +++ Docs/Documentation/Migration/4.x-5.0.md | 56 ++ Docs/Documentation/Migration/6.x-7.0.md | 18 + Docs/Documentation/Overview.md | 19 + Docs/Documentation/SocialAuthenticate.md | 97 ++ Docs/Documentation/Translations.md | 17 + Docs/Documentation/UserHelper.md | 85 ++ Docs/Home.md | 32 + LICENSE.txt | 26 + README.md | 74 ++ config/Migrations/20150513201111_initial.php | 152 +++ .../20161031101316_AddSecretToUsers.php | 43 + config/Migrations/schema-dump-default.lock | Bin 0 -> 7938 bytes config/bootstrap.php | 49 + config/permissions.php | 91 ++ config/routes.php | 52 + config/users.php | 206 ++++ nbproject/project.properties | 7 + nbproject/project.xml | 9 + phpunit.xml.dist | 36 + .../DefaultTwoFactorAuthenticationChecker.php | 44 + .../Exception/InvalidProviderException.php | 31 + .../Exception/InvalidSettingsException.php | 31 + .../MissingEventListenerException.php | 30 + .../MissingProviderConfigurationException.php | 31 + src/Auth/Social/Mapper/AbstractMapper.php | 119 +++ src/Auth/Social/Mapper/Amazon.php | 43 + src/Auth/Social/Mapper/Facebook.php | 52 + src/Auth/Social/Mapper/Google.php | 43 + src/Auth/Social/Mapper/Instagram.php | 43 + src/Auth/Social/Mapper/LinkedIn.php | 28 + src/Auth/Social/Mapper/Pinterest.php | 24 + src/Auth/Social/Mapper/Tumblr.php | 46 + src/Auth/Social/Mapper/Twitter.php | 59 ++ src/Auth/Social/Util/SocialUtils.php | 35 + src/Auth/SocialAuthenticate.php | 488 ++++++++++ .../TwoFactorAuthenticationCheckerFactory.php | 39 + ...woFactorAuthenticationCheckerInterface.php | 30 + src/Controller/AppController.php | 36 + .../GoogleAuthenticatorComponent.php | 84 ++ .../Component/RememberMeComponent.php | 159 +++ src/Controller/Component/SetupComponent.php | 33 + .../Component/UsersAuthComponent.php | 247 +++++ src/Controller/SocialAccountsController.php | 94 ++ .../Traits/CustomUsersTableTrait.php | 51 + src/Controller/Traits/LinkSocialTrait.php | 237 +++++ .../Traits/PasswordManagementTrait.php | 180 ++++ src/Controller/Traits/ProfileTrait.php | 61 ++ src/Controller/Traits/ReCaptchaTrait.php | 57 ++ src/Controller/Traits/RegisterTrait.php | 155 +++ src/Controller/Traits/SimpleCrudTrait.php | 138 +++ src/Controller/Traits/SocialTrait.php | 49 + src/Controller/Traits/UserValidationTrait.php | 123 +++ src/Controller/UsersController.php | 41 + .../AccountAlreadyActiveException.php | 28 + src/Exception/AccountNotActiveException.php | 30 + src/Exception/BadConfigurationException.php | 28 + src/Exception/MissingEmailException.php | 28 + src/Exception/MissingProviderException.php | 28 + src/Exception/TokenExpiredException.php | 28 + src/Exception/UserAlreadyActiveException.php | 28 + src/Exception/UserNotActiveException.php | 28 + src/Exception/UserNotFoundException.php | 28 + src/Exception/WrongPasswordException.php | 28 + src/Locale/Users.pot | 821 ++++++++++++++++ src/Locale/ar_OM/Users.mo | Bin 0 -> 18521 bytes src/Locale/ar_OM/Users.po | 819 ++++++++++++++++ src/Locale/es/Users.mo | Bin 0 -> 15243 bytes src/Locale/es/Users.po | 854 ++++++++++++++++ src/Locale/fr_FR/Users.mo | Bin 0 -> 16147 bytes src/Locale/fr_FR/Users.po | 837 ++++++++++++++++ src/Locale/hu_HU/Users.mo | Bin 0 -> 14725 bytes src/Locale/hu_HU/Users.po | 816 ++++++++++++++++ src/Locale/it_IT/Users.mo | Bin 0 -> 15385 bytes src/Locale/it_IT/Users.po | 783 +++++++++++++++ src/Locale/pl/Users.mo | Bin 0 -> 14520 bytes src/Locale/pl/Users.po | 811 ++++++++++++++++ src/Locale/pt_BR/Users.mo | Bin 0 -> 15088 bytes src/Locale/pt_BR/Users.po | 908 ++++++++++++++++++ src/Locale/sv/Users.mo | Bin 0 -> 14831 bytes src/Locale/sv/Users.po | 864 +++++++++++++++++ src/Locale/tr_TR/Users.mo | Bin 0 -> 15267 bytes src/Locale/tr_TR/Users.po | 819 ++++++++++++++++ src/Mailer/UsersMailer.php | 81 ++ src/Model/Behavior/AuthFinderBehavior.php | 62 ++ src/Model/Behavior/BaseTokenBehavior.php | 59 ++ src/Model/Behavior/LinkSocialBehavior.php | 141 +++ src/Model/Behavior/PasswordBehavior.php | 159 +++ src/Model/Behavior/RegisterBehavior.php | 210 ++++ src/Model/Behavior/SocialAccountBehavior.php | 152 +++ src/Model/Behavior/SocialBehavior.php | 261 +++++ src/Model/Entity/SocialAccount.php | 41 + src/Model/Entity/User.php | 163 ++++ src/Model/Table/SocialAccountsTable.php | 133 +++ src/Model/Table/UsersTable.php | 185 ++++ src/Shell/UsersShell.php | 404 ++++++++ src/Template/Email/html/reset_password.ctp | 35 + .../Email/html/social_account_validation.ctp | 40 + src/Template/Email/html/validation.ctp | 35 + src/Template/Email/text/reset_password.ctp | 29 + .../Email/text/social_account_validation.ctp | 31 + src/Template/Email/text/validation.ctp | 29 + src/Template/Layout/Email/html/default.ctp | 20 + src/Template/Layout/Email/text/default.ctp | 13 + src/Template/Users/add.ctp | 36 + src/Template/Users/change_password.ctp | 27 + src/Template/Users/edit.ctp | 77 ++ src/Template/Users/index.ctp | 55 ++ src/Template/Users/login.ctp | 50 + src/Template/Users/profile.ctp | 78 ++ src/Template/Users/register.ctp | 38 + src/Template/Users/request_reset_password.ctp | 10 + .../Users/resend_token_validation.ctp | 22 + src/Template/Users/social_email.ctp | 21 + src/Template/Users/verify.ctp | 20 + src/Template/Users/view.ctp | 90 ++ src/Traits/RandomStringTrait.php | 30 + src/View/Helper/AuthLinkHelper.php | 68 ++ src/View/Helper/UserHelper.php | 254 +++++ tests/App/Controller/AppController.php | 33 + tests/App/Mailer/OverrideMailer.php | 34 + .../text/custom_template_in_app_namespace.ctp | 1 + .../Template/Layout/Email/html/default.ctp | 2 + .../Template/Layout/Email/text/default.ctp | 2 + tests/Fixture/PostsFixture.php | 60 ++ tests/Fixture/PostsUsersFixture.php | 60 ++ tests/Fixture/SocialAccountsFixture.php | 141 +++ tests/Fixture/UsersFixture.php | 267 +++++ ...aultTwoFactorAuthenticationCheckerTest.php | 67 ++ .../InvalidProviderExceptionTest.php | 46 + .../InvalidSettingsExceptionTest.php | 46 + .../MissingEventListenerExceptionTest.php | 45 + ...singProviderConfigurationExceptionTest.php | 46 + .../Auth/Social/Mapper/FacebookTest.php | 91 ++ .../Auth/Social/Mapper/GoogleTest.php | 73 ++ .../Auth/Social/Mapper/InstagramTest.php | 72 ++ .../Auth/Social/Mapper/LinkedInTest.php | 75 ++ .../Auth/Social/Mapper/TwitterTest.php | 71 ++ .../TestCase/Auth/SocialAuthenticateTest.php | 644 +++++++++++++ ...FactorAuthenticationCheckerFactoryTest.php | 44 + .../GoogleAuthenticatorComponentTest.php | 136 +++ .../Component/RememberMeComponentTest.php | 194 ++++ .../Component/UsersAuthComponentTest.php | 515 ++++++++++ .../SocialAccountsControllerTest.php | 204 ++++ .../Controller/Traits/BaseTraitTest.php | 220 +++++ .../Traits/CustomUsersTableTraitTest.php | 41 + .../Controller/Traits/LinkSocialTraitTest.php | 825 ++++++++++++++++ .../Controller/Traits/LoginTraitTest.php | 840 ++++++++++++++++ .../Traits/PasswordManagementTraitTest.php | 470 +++++++++ .../Controller/Traits/ProfileTraitTest.php | 113 +++ .../Controller/Traits/RecaptchaTraitTest.php | 123 +++ .../Controller/Traits/RegisterTraitTest.php | 399 ++++++++ .../Controller/Traits/SimpleCrudTraitTest.php | 306 ++++++ .../Controller/Traits/SocialTraitTest.php | 180 ++++ .../Traits/UserValidationTraitTest.php | 243 +++++ .../AccountAlreadyActiveExceptionTest.php | 43 + .../AccountNotActiveExceptionTest.php | 45 + .../BadConfigurationExceptionTest.php | 43 + .../Exception/MissingEmailExceptionTest.php | 43 + .../MissingProviderExceptionTest.php | 43 + .../Exception/TokenExpiredExceptionTest.php | 43 + .../UserAlreadyActiveExceptionTest.php | 43 + .../Exception/UserNotActiveExceptionTest.php | 43 + .../Exception/UserNotFoundExceptionTest.php | 43 + .../Exception/WrongPasswordExceptionTest.php | 43 + tests/TestCase/Mailer/UsersMailerTest.php | 172 ++++ .../Model/Behavior/AuthFinderBehaviorTest.php | 104 ++ .../Model/Behavior/LinkSocialBehaviorTest.php | 363 +++++++ .../Model/Behavior/PasswordBehaviorTest.php | 237 +++++ .../Model/Behavior/RegisterBehaviorTest.php | 320 ++++++ .../Behavior/SocialAccountBehaviorTest.php | 141 +++ .../Model/Behavior/SocialBehaviorTest.php | 388 ++++++++ tests/TestCase/Model/Entity/UserTest.php | 206 ++++ .../Model/Table/SocialAccountsTableTest.php | 74 ++ tests/TestCase/Model/Table/UsersTableTest.php | 312 ++++++ tests/TestCase/Shell/UsersShellTest.php | 418 ++++++++ .../TestCase/Traits/RandomStringTraitTest.php | 43 + .../View/Helper/AuthLinkHelperTest.php | 156 +++ tests/TestCase/View/Helper/UserHelperTest.php | 380 ++++++++ tests/bootstrap.php | 130 +++ tests/config/routes.php | 35 + webroot/empty | 0 webroot/img/avatar_placeholder.png | Bin 0 -> 4015 bytes 193 files changed, 27286 insertions(+) create mode 100644 .semver create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 Docs/Documentation/Configuration.md create mode 100644 Docs/Documentation/Events.md create mode 100644 Docs/Documentation/Extending-the-Plugin.md create mode 100644 Docs/Documentation/Google-Two-Factor-Authenticator.md create mode 100644 Docs/Documentation/GoogleAuthenticator/App.png create mode 100644 Docs/Documentation/GoogleAuthenticator/FirstLogin.png create mode 100644 Docs/Documentation/Installation.md create mode 100644 Docs/Documentation/Migration/4.x-5.0.md create mode 100644 Docs/Documentation/Migration/6.x-7.0.md create mode 100644 Docs/Documentation/Overview.md create mode 100644 Docs/Documentation/SocialAuthenticate.md create mode 100644 Docs/Documentation/Translations.md create mode 100644 Docs/Documentation/UserHelper.md create mode 100644 Docs/Home.md create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 config/Migrations/20150513201111_initial.php create mode 100644 config/Migrations/20161031101316_AddSecretToUsers.php create mode 100644 config/Migrations/schema-dump-default.lock create mode 100644 config/bootstrap.php create mode 100644 config/permissions.php create mode 100644 config/routes.php create mode 100644 config/users.php create mode 100644 nbproject/project.properties create mode 100644 nbproject/project.xml create mode 100644 phpunit.xml.dist create mode 100644 src/Auth/DefaultTwoFactorAuthenticationChecker.php create mode 100644 src/Auth/Exception/InvalidProviderException.php create mode 100644 src/Auth/Exception/InvalidSettingsException.php create mode 100644 src/Auth/Exception/MissingEventListenerException.php create mode 100644 src/Auth/Exception/MissingProviderConfigurationException.php create mode 100644 src/Auth/Social/Mapper/AbstractMapper.php create mode 100644 src/Auth/Social/Mapper/Amazon.php create mode 100644 src/Auth/Social/Mapper/Facebook.php create mode 100644 src/Auth/Social/Mapper/Google.php create mode 100644 src/Auth/Social/Mapper/Instagram.php create mode 100644 src/Auth/Social/Mapper/LinkedIn.php create mode 100644 src/Auth/Social/Mapper/Pinterest.php create mode 100644 src/Auth/Social/Mapper/Tumblr.php create mode 100644 src/Auth/Social/Mapper/Twitter.php create mode 100644 src/Auth/Social/Util/SocialUtils.php create mode 100755 src/Auth/SocialAuthenticate.php create mode 100644 src/Auth/TwoFactorAuthenticationCheckerFactory.php create mode 100644 src/Auth/TwoFactorAuthenticationCheckerInterface.php create mode 100644 src/Controller/AppController.php create mode 100644 src/Controller/Component/GoogleAuthenticatorComponent.php create mode 100644 src/Controller/Component/RememberMeComponent.php create mode 100644 src/Controller/Component/SetupComponent.php create mode 100644 src/Controller/Component/UsersAuthComponent.php create mode 100644 src/Controller/SocialAccountsController.php create mode 100644 src/Controller/Traits/CustomUsersTableTrait.php create mode 100644 src/Controller/Traits/LinkSocialTrait.php create mode 100644 src/Controller/Traits/PasswordManagementTrait.php create mode 100644 src/Controller/Traits/ProfileTrait.php create mode 100644 src/Controller/Traits/ReCaptchaTrait.php create mode 100644 src/Controller/Traits/RegisterTrait.php create mode 100644 src/Controller/Traits/SimpleCrudTrait.php create mode 100644 src/Controller/Traits/SocialTrait.php create mode 100644 src/Controller/Traits/UserValidationTrait.php create mode 100644 src/Controller/UsersController.php create mode 100644 src/Exception/AccountAlreadyActiveException.php create mode 100644 src/Exception/AccountNotActiveException.php create mode 100644 src/Exception/BadConfigurationException.php create mode 100644 src/Exception/MissingEmailException.php create mode 100644 src/Exception/MissingProviderException.php create mode 100644 src/Exception/TokenExpiredException.php create mode 100644 src/Exception/UserAlreadyActiveException.php create mode 100644 src/Exception/UserNotActiveException.php create mode 100644 src/Exception/UserNotFoundException.php create mode 100644 src/Exception/WrongPasswordException.php create mode 100644 src/Locale/Users.pot create mode 100644 src/Locale/ar_OM/Users.mo create mode 100644 src/Locale/ar_OM/Users.po create mode 100644 src/Locale/es/Users.mo create mode 100644 src/Locale/es/Users.po create mode 100644 src/Locale/fr_FR/Users.mo create mode 100644 src/Locale/fr_FR/Users.po create mode 100644 src/Locale/hu_HU/Users.mo create mode 100644 src/Locale/hu_HU/Users.po create mode 100644 src/Locale/it_IT/Users.mo create mode 100644 src/Locale/it_IT/Users.po create mode 100644 src/Locale/pl/Users.mo create mode 100644 src/Locale/pl/Users.po create mode 100644 src/Locale/pt_BR/Users.mo create mode 100644 src/Locale/pt_BR/Users.po create mode 100644 src/Locale/sv/Users.mo create mode 100644 src/Locale/sv/Users.po create mode 100644 src/Locale/tr_TR/Users.mo create mode 100644 src/Locale/tr_TR/Users.po create mode 100644 src/Mailer/UsersMailer.php create mode 100644 src/Model/Behavior/AuthFinderBehavior.php create mode 100644 src/Model/Behavior/BaseTokenBehavior.php create mode 100644 src/Model/Behavior/LinkSocialBehavior.php create mode 100644 src/Model/Behavior/PasswordBehavior.php create mode 100644 src/Model/Behavior/RegisterBehavior.php create mode 100644 src/Model/Behavior/SocialAccountBehavior.php create mode 100644 src/Model/Behavior/SocialBehavior.php create mode 100644 src/Model/Entity/SocialAccount.php create mode 100644 src/Model/Entity/User.php create mode 100644 src/Model/Table/SocialAccountsTable.php create mode 100644 src/Model/Table/UsersTable.php create mode 100644 src/Shell/UsersShell.php create mode 100644 src/Template/Email/html/reset_password.ctp create mode 100644 src/Template/Email/html/social_account_validation.ctp create mode 100644 src/Template/Email/html/validation.ctp create mode 100644 src/Template/Email/text/reset_password.ctp create mode 100644 src/Template/Email/text/social_account_validation.ctp create mode 100644 src/Template/Email/text/validation.ctp create mode 100644 src/Template/Layout/Email/html/default.ctp create mode 100644 src/Template/Layout/Email/text/default.ctp create mode 100644 src/Template/Users/add.ctp create mode 100644 src/Template/Users/change_password.ctp create mode 100644 src/Template/Users/edit.ctp create mode 100644 src/Template/Users/index.ctp create mode 100644 src/Template/Users/login.ctp create mode 100644 src/Template/Users/profile.ctp create mode 100644 src/Template/Users/register.ctp create mode 100644 src/Template/Users/request_reset_password.ctp create mode 100644 src/Template/Users/resend_token_validation.ctp create mode 100644 src/Template/Users/social_email.ctp create mode 100644 src/Template/Users/verify.ctp create mode 100644 src/Template/Users/view.ctp create mode 100644 src/Traits/RandomStringTrait.php create mode 100644 src/View/Helper/AuthLinkHelper.php create mode 100644 src/View/Helper/UserHelper.php create mode 100644 tests/App/Controller/AppController.php create mode 100644 tests/App/Mailer/OverrideMailer.php create mode 100644 tests/App/Template/Email/text/custom_template_in_app_namespace.ctp create mode 100644 tests/App/Template/Layout/Email/html/default.ctp create mode 100644 tests/App/Template/Layout/Email/text/default.ctp create mode 100644 tests/Fixture/PostsFixture.php create mode 100644 tests/Fixture/PostsUsersFixture.php create mode 100644 tests/Fixture/SocialAccountsFixture.php create mode 100644 tests/Fixture/UsersFixture.php create mode 100644 tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php create mode 100644 tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php create mode 100644 tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php create mode 100644 tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php create mode 100644 tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php create mode 100644 tests/TestCase/Auth/Social/Mapper/FacebookTest.php create mode 100644 tests/TestCase/Auth/Social/Mapper/GoogleTest.php create mode 100644 tests/TestCase/Auth/Social/Mapper/InstagramTest.php create mode 100644 tests/TestCase/Auth/Social/Mapper/LinkedInTest.php create mode 100644 tests/TestCase/Auth/Social/Mapper/TwitterTest.php create mode 100644 tests/TestCase/Auth/SocialAuthenticateTest.php create mode 100644 tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php create mode 100644 tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php create mode 100644 tests/TestCase/Controller/Component/RememberMeComponentTest.php create mode 100644 tests/TestCase/Controller/Component/UsersAuthComponentTest.php create mode 100644 tests/TestCase/Controller/SocialAccountsControllerTest.php create mode 100644 tests/TestCase/Controller/Traits/BaseTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/LinkSocialTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/LoginTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/ProfileTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/RecaptchaTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/RegisterTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/SocialTraitTest.php create mode 100644 tests/TestCase/Controller/Traits/UserValidationTraitTest.php create mode 100644 tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php create mode 100644 tests/TestCase/Exception/AccountNotActiveExceptionTest.php create mode 100644 tests/TestCase/Exception/BadConfigurationExceptionTest.php create mode 100644 tests/TestCase/Exception/MissingEmailExceptionTest.php create mode 100644 tests/TestCase/Exception/MissingProviderExceptionTest.php create mode 100644 tests/TestCase/Exception/TokenExpiredExceptionTest.php create mode 100644 tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php create mode 100644 tests/TestCase/Exception/UserNotActiveExceptionTest.php create mode 100644 tests/TestCase/Exception/UserNotFoundExceptionTest.php create mode 100644 tests/TestCase/Exception/WrongPasswordExceptionTest.php create mode 100644 tests/TestCase/Mailer/UsersMailerTest.php create mode 100644 tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php create mode 100644 tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php create mode 100644 tests/TestCase/Model/Behavior/PasswordBehaviorTest.php create mode 100644 tests/TestCase/Model/Behavior/RegisterBehaviorTest.php create mode 100644 tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php create mode 100644 tests/TestCase/Model/Behavior/SocialBehaviorTest.php create mode 100644 tests/TestCase/Model/Entity/UserTest.php create mode 100644 tests/TestCase/Model/Table/SocialAccountsTableTest.php create mode 100644 tests/TestCase/Model/Table/UsersTableTest.php create mode 100644 tests/TestCase/Shell/UsersShellTest.php create mode 100644 tests/TestCase/Traits/RandomStringTraitTest.php create mode 100644 tests/TestCase/View/Helper/AuthLinkHelperTest.php create mode 100644 tests/TestCase/View/Helper/UserHelperTest.php create mode 100644 tests/bootstrap.php create mode 100644 tests/config/routes.php create mode 100644 webroot/empty create mode 100644 webroot/img/avatar_placeholder.png diff --git a/.semver b/.semver new file mode 100644 index 000000000..af406a57b --- /dev/null +++ b/.semver @@ -0,0 +1,5 @@ +--- +:major: 8 +:minor: 0 +:patch: 2 +:special: '' diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..e71ec741f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,50 @@ +language: php + +php: + - 5.6 + - 7.0 + - 7.1 + - 7.2 + +sudo: false + +env: + matrix: + - DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' + - DB=pgsql db_dsn='postgres://postgres@127.0.0.1/cakephp_test' + - DB=sqlite db_dsn='sqlite:///:memory:' + + global: + - DEFAULT=1 + +matrix: + fast_finish: true + + include: + - php: 7.1 + env: PHPCS=1 DEFAULT=0 + + - php: 7.1 + env: CODECOVERAGE=1 DEFAULT=0 DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' + +before_script: + - composer self-update + - composer install --prefer-dist --no-interaction + + - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'CREATE DATABASE cakephp_test; GRANT ALL PRIVILEGES ON cakephp_test.* TO travis@localhost;'; fi" + - sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi" + + - sh -c "if [ '$PHPCS' = '1' ]; then composer require 'cakephp/cakephp-codesniffer:@stable'; fi" + - sh -c "if [ '$COVERALLS' = '1' ]; then composer require --dev 'satooshi/php-coveralls:^2.0'; fi" + + - sh -c "if [ '$COVERALLS' = '1' ]; then mkdir -p build/logs; fi" + +script: + - sh -c "if [ '$DEFAULT' = '1' ]; then ./vendor/bin/phpunit --stderr; fi" + - sh -c "if [ '$PHPCS' = '1' ]; then ./vendor/bin/phpcs -p -n --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests; fi" + - sh -c "if [ '$CODECOVERAGE' = '1' ]; then phpunit --coverage-clover=clover.xml || true; fi" + - sh -c "if [ '$CODECOVERAGE' = '1' ]; then wget -O codecov.sh https://codecov.io/bash; fi" + - sh -c "if [ '$CODECOVERAGE' = '1' ]; then bash codecov.sh; fi" + +notifications: + email: false diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..7ba444c97 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,159 @@ +Changelog +========= + +Releases for CakePHP 3 +------------- + +* 8.0.2 + * Add default role for users registered via social login + +* 8.0.1 + * Fixed 2fa link preserve querystring + +* 8.0.0 + * Added new events `Users.Component.UsersAuth.onExpiredToken` and `Users.Component.UsersAuth.afterResendTokenValidation` + * Added 2 factor authentication checkers to allow customization + * Added Mapper classes to social auth services as a way to generalize url/avatar retrieval + * Fix issues with recent changes in Facebook API + * Added new translations + * Improved customization options for recaptcha integration + +* 7.0.2 + * Fixed an issue with 2FA only working on the second try + +* 7.0.1 + * Fixed a security issue in 2 factor authentication, reported by @ndm2 + * Updated to cakedc/auth ^3.0 + * Documentation fixes + +* 7.0.0 + * Removed deprecations for CakePHP 3.6 + * Added a new `UsersAuthComponent::EVENT_AFTER_CHANGE_PASSWORD` + * Updated docs + +* 6.0.0 + * Removed deprecations and orWhere usage + * Amazon login implemented + * Fixed issues with login via twitter + * Updated Facebook Graph version to 2.8 + * Fixed flash error messages on logic + * Added link social account feature for twitter + * Switched to codecov + +* 5.2.0 + * Compatible with 3.5, deprecations will be removed in next major version of the plugin + * Username is now custom in SocialBehavior + * Better handling of the RememberMe checkbox + * Updated CakeDC/Auth to use ^2.0 + * Use of UsersMailer class, and allow override of the emails sent by the plugin + * Better token generation via randomBytes + * Improved documentation + * Fixed bugs reported + +* 5.1.0 + * New resend validation method in RegisterBehavior + * Allow upgrade to CakePHP 3.5.x + * New feature connect social account + * New polish translations + * Fixed bugs reported + +* 5.0.3 + * Implemented event dispatching on social login + * Fixed bugs reported + * Don't check for allowed actions in other controllers + +* 5.0.2 + * Fixed bug parsing rule urls when application installed in a subdirectory + +* 5.0.1 + * Bugfix release + * Minor BR language improvements + +* 5.0.0 + * Some Auth objects refactored into https://github.com/CakeDC/auth + * Upgrade to CakePHP 3.4 + +* 4.2.1 + * Improvements in unit tests + +* 4.2.0 + * New configuration param `Users.Registration.defaultRole` to set the default role on user registration or addUser Shell action + +* 4.1.3 + * Configurable rememberMe checkbox status + * Update brazilian portuguese translations + * Add active finder to SocialAccountsTable + * Improvements in UsersShell for superuser add options + * Update to robthree/twofactorauth 1.6 + * UserHelper improvements + +* 4.1.2 + * Fix RememberMe redirect + * Fix AuthLink rendering inside Cells + +* 4.1.1 + * Add missing password field in add user + +* 4.1.0 + * Add reset action for Google Authenticator + +* 4.0.0 + * Add Google Authenticator + * Add improvements to SimpleRbac, like star to invert rules and `user.` prefix to match values from the user array + * Add `allowed` to manage the AuthLinkHelper when action is allowed + * Add option to configure the api table and finder in ApiKeyAuthenticate + +* 3.2.5 + * Fixed RegisterBehavior api, make getRegisterValidators public. + +* 3.2.3 + * Added compatibility with CakePHP 3.3+ + * Fixed several bugs, including regression issue with Facebook login & improvements + +* 3.2.2 + * Fix bug with socialLogin links not being displayed for unauthenticated users + +* 3.2.1 + * New Translations (see https://github.com/CakeDC/users/blob/master/Docs/Documentation/Translations.md) + * Stateless API Authenticate support + * Prefix and extension support in permission rules (RBAC) + * Improved registration and reset password user already logged in logic + * Several bugfixes + * AuthLinkHelper added to render links if user is allowed only + +* 3.1.5 + * SocialAuthenticate improvements + * Authorize Rules. Owner rule + * Docs improvements + +* 3.1.4 + * SocialAuthenticate refactored to drop Opauth in favor of Muffin/OAuth2 and league/oauth2 + +* 3.1.3 + * UserHelper improvements + +* 3.1.2 + * Fixes in RBAC permission matchers + +* 3.1.0 Migration to CakePHP 3.0 + * Unit test coverage improvements + * Refactor UsersTable to Behavior + * Add google authentication + * Add reCaptcha + * Link social accounts in profile + +Releases for CakePHP 2 +------------- + +* 2.1.3 + * Fixed unit tests for compatibility with CakePHP 2.7 + +* 2.1.2 + * Minor improvements + * New translations (german and portuguese) + +* 2.1.1 + * Forgot password + +* 2.1.0 + * Bugfixes and improvements diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..653b64f7c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +Contributing +============ + +This repository follows the [CakeDC Plugin Standard](https://www.cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](https://www.cakedc.com/contribution-guidelines) for detailed instructions. diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md new file mode 100644 index 000000000..f52015acb --- /dev/null +++ b/Docs/Documentation/Configuration.md @@ -0,0 +1,195 @@ +Configuration +============= + +Overriding the default configuration +------------------------- + +For easier configuration, you can specify an array of config files to override the default plugin keys this way: + +config/bootstrap.php +``` +// The following configuration setting must be set before loading the Users plugin +Configure::write('Users.config', ['users']); +Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); +Configure::write('Users.Social.login', true); //to enable social login +``` + +Configuration for social login +--------------------- + +Create the facebook, twitter, etc applications you want to use and setup the configuration like this: +In this example, we are using 2 providers: facebook and twitter. Note you'll need to add the providers to +your composer.json file. + +``` +$ composer require league/oauth2-facebook:@stable +$ composer require league/oauth1-client:@stable +``` + +NOTE: twitter uses league/oauth1-client package + +config/bootstrap.php +``` +Configure::write('OAuth.providers.facebook.options.clientId', 'YOUR APP ID'); +Configure::write('OAuth.providers.facebook.options.clientSecret', 'YOUR APP SECRET'); + +Configure::write('OAuth.providers.twitter.options.clientId', 'YOUR APP ID'); +Configure::write('OAuth.providers.twitter.options.clientSecret', 'YOUR APP SECRET'); +``` + +Or use the config override option when loading the plugin (see above) + +Additionally you will see you can configure two more keys for each provider: + +* linkSocialUri (default: /link-social/**provider**), +* callbackLinkSocialUri(default: /callback-link-social/**provider**) + +Those keys are needed to link an existing user account to a third-party account. **Remember to add the callback to your thrid-party app** + +Configuration for reCaptcha +--------------------- +``` +Configure::write('Users.reCaptcha.key', 'YOUR RECAPTCHA KEY'); +Configure::write('Users.reCaptcha.secret', 'YOUR RECAPTCHA SECRET'); +Configure::write('Users.reCaptcha.registration', true); //enable on registration +Configure::write('Users.reCaptcha.login', true); //enable on login +``` + + +Configuration options +--------------------- + +The plugin is configured via the Configure class. Check the `vendor/cakedc/users/config/users.php` +for a complete list of all the configuration keys. + +Loading the UsersAuthComponent and using the right configuration values will setup the Users plugin, +the AuthComponent and the OAuth component for your application. + +If you prefer to setup AuthComponent by yourself, you'll need to load AuthComponent before UsersAuthComponent +and set +``` +Configure::write('Users.auth', false); +``` + +Interesting UsersAuthComponent options and defaults + +NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/users/config/users.php` for the complete list + +``` + 'Users' => [ + // Table used to manage users + 'table' => 'CakeDC/Users.Users', + // Controller used to manage users plugin features & actions + 'controller' => 'CakeDC/Users.Users', + // configure Auth component + 'auth' => true, + 'Email' => [ + // determines if the user should include email + 'required' => true, + // determines if registration workflow includes email validation + 'validate' => true, + ], + 'Registration' => [ + // determines if the register is enabled + 'active' => true, + // determines if the reCaptcha is enabled for registration + 'reCaptcha' => true, + //ensure user is active (confirmed email) to reset his password + 'ensureActive' => false, + // default role name used in registration + 'defaultRole' => 'user', + ], + 'Tos' => [ + // determines if the user should include tos accepted + 'required' => true, + ], + 'Social' => [ + // enable social login + 'login' => false, + ], + // Avatar placeholder + 'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'], + 'RememberMe' => [ + // configure Remember Me component + 'active' => true, + ], + ], +// default configuration used to auto-load the Auth Component, override to change the way Auth works + 'Auth' => [ + 'authenticate' => [ + 'all' => [ + 'finder' => 'active', + ], + 'CakeDC/Auth.RememberMe', + 'Form', + ], + 'authorize' => [ + 'CakeDC/Auth.Superuser', + 'CakeDC/Auth.SimpleRbac', + ], + ], +]; + +``` + +Default Authenticate and Authorize Objects used +------------------------ + +Using the UsersAuthComponent default initialization, the component will load the following objects into AuthComponent: +* Authenticate + * 'Form' + * 'CakeDC/Users.Social' check [SocialAuthenticate](SocialAuthenticate.md) for configuration options + * 'CakeDC/Auth.RememberMe' check [RememberMeAuthenticate](https://github.com/CakeDC/auth/blob/master/src/RememberMeAuthenticate.php) for configuration options + * 'CakeDC/Auth.ApiKey' check [ApiKeyAuthenticate](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/ApiKeyAuthenticate.md) for configuration options +* Authorize + * 'CakeDC/Auth.Superuser' check [SuperuserAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SuperuserAuthorize.md) for configuration options + * 'CakeDC/Auth.SimpleRbac' check [SimpleRbacAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SimpleRbacAuthorize.md) for configuration options + +## Using the user's email to login + +You need to configure 2 things: +* Change the Auth.authenticate.Form.fields configuration to let AuthComponent use the email instead of the username for user identify. Add this line to your bootstrap.php file, after CakeDC/Users Plugin is loaded + +```php +Configure::write('Auth.authenticate.Form.fields.username', 'email'); +``` + +* Override the login.ctp template to change the Form->control to "email". Add (or copy from the https://github.com/CakeDC/users/blob/master/src/Template/Users/login.ctp) the file login.ctp to path /src/Template/Plugin/CakeDC/Users/Users/login.ctp and ensure it has the following content + +```php + // ... inside the Form + Form->control('email', ['required' => true]) ?> + Form->control('password', ['required' => true]) ?> + // ... rest of your login.ctp code +``` + + + + +Email Templates +--------------- + +To modify the templates as needed copy them to your application + +``` +cp -r vendor/cakedc/users/src/Template/Email/* src/Template/Plugin/CakeDC/Users/Email/ +``` + +Then customize the email templates as you need under the src/Template/Plugin/CakeDC/Users/Email/ directory + +Plugin Templates +--------------- + +Similar to Email Templates customization, follow the CakePHP conventions to put your new templates under +src/Template/Plugin/CakeDC/Users/[Controller]/[view].ctp + +Check http://book.cakephp.org/3.0/en/plugins.html#overriding-plugin-templates-from-inside-your-application + +Flash Messages +--------------- + +To modify the flash messages, use the standard PO file provided by the plugin and customize the messages +Check http://book.cakephp.org/3.0/en/core-libraries/internationalization-and-localization.html#setting-up-translations +for more details about how the PO files should be managed in your application. + +We've included an updated POT file with all the `Users` domain keys for your customization. diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md new file mode 100644 index 000000000..1308d0705 --- /dev/null +++ b/Docs/Documentation/Events.md @@ -0,0 +1,60 @@ +Events +====== + +The events in this plugin follow these conventions `...`: + +* `Users.Component.UsersAuth.isAuthorized` +* `Users.Component.UsersAuth.beforeLogin` +* `Users.Component.UsersAuth.afterLogin` +* `Users.Component.UsersAuth.failedSocialLogin` +* `Users.Component.UsersAuth.afterCookieLogin` +* `Users.Component.UsersAuth.beforeRegister` +* `Users.Component.UsersAuth.afterRegister` +* `Users.Component.UsersAuth.beforeLogout` +* `Users.Component.UsersAuth.afterLogout` +* `Users.Component.UsersAuth.beforeSocialLoginUserCreate` +* `Users.Component.UsersAuth.afterResetPassword` +* `Users.Component.UsersAuth.onExpiredToken` +* `Users.Component.UsersAuth.afterResendTokenValidation` + +The events allow you to inject data into the plugin on the before* plugins and use the data for your +own business login in the after* events, for example + +``` +/** + * Forced login using a beforeLogin event + */ +public function eventLogin() +{ + $this->eventManager()->on(UsersAuthComponent::EVENT_BEFORE_LOGIN, function () { + //the callback function should return the user data array to force login + return [ + 'id' => 1337, + 'username' => 'forceLogin', + 'email' => 'event@example.com', + 'active' => true, + ]; + }); + $this->login(); + $this->render('login'); +} + +/** + * beforeRegister event + */ +public function eventRegister() +{ + $this->eventManager()->on(UsersAuthComponent::EVENT_BEFORE_REGISTER, function ($event) { + //the callback function should return the user data array to force register + return $event->data['usersTable']->newEntity([ + 'username' => 'forceEventRegister', + 'email' => 'eventregister@example.com', + 'password' => 'password', + 'active' => true, + 'tos' => true, + ]); + }); + $this->register(); + $this->render('register'); +} +``` diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md new file mode 100644 index 000000000..fec58928a --- /dev/null +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -0,0 +1,219 @@ +Extending the Plugin +==================== + +Extending the Model (Table/Entity) +------------------- + +Create a new Table and Entity in your app, matching the table you want to use for storing the +users data. Check the initial users migration to know the default columns expected in the table. +If your column names doesn't match the columns in your current table, you could use the Entity to +match the colums using accessors & mutators as described here http://book.cakephp.org/3.0/en/orm/entities.html#accessors-mutators + +Example: we are going to use a custom table ```my_users``` in our application , which has a field named ``is_active`` instead of the default ``active``. +* Create a new Table under src/Model/Table/MyUsersTable.php + +```php +namespace App\Model\Table; + +use CakeDC\Users\Model\Table\UsersTable; + +/** + * Application specific Users Table with non plugin conform field(s) + */ +class MyUsersTable extends UsersTable +{ +} +``` + +* Create a new Entity under src/Model/Entity/MyUser.php + +```php +namespace App\Model\Entity; + +use CakeDC\Users\Model\Entity\User; + +/** + * Application specific User Entity with non plugin conform field(s) + */ +class MyUser extends User +{ + /** + * Map CakeDC's User.active field to User.is_active when getting + * + * @return mixed The value of the mapped property. + */ + protected function _getActive() + { + return $this->_properties['is_active']; + } + + /** + * Map CakeDC's User.active field to User.is_active when setting + * + * @param mixed $value The value to set. + * @return static + */ + protected function _setActive($value) + { + $this->set('is_active', $value); + return $value; + } +} +``` + +* Pass the new table configuration to Users Plugin Configuration + +config/bootstrap.php +``` +Configure::write('Users.config', ['users']); +Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); +``` + +Then in your config/users.php +``` +return [ + 'Users.table' => 'MyUsers', +]; +``` + +Now the Users Plugin will use MyUsers Table and Entity to register and login user in. Use the +Entity as shown above to match your own columns in case they don't match the default column names: + +```sql +CREATE TABLE IF NOT EXISTS `users` ( + `id` char(36) NOT NULL, + `username` varchar(255) NOT NULL, + `email` varchar(255) DEFAULT NULL, + `password` varchar(255) NOT NULL, + `first_name` varchar(50) DEFAULT NULL, + `last_name` varchar(50) DEFAULT NULL, + `token` varchar(255) DEFAULT NULL, + `token_expires` datetime DEFAULT NULL, + `api_token` varchar(255) DEFAULT NULL, + `activation_date` datetime DEFAULT NULL, + `tos_date` datetime DEFAULT NULL, + `active` int(1) NOT NULL DEFAULT '0', + `is_superuser` int(1) NOT NULL DEFAULT '0', + `role` varchar(255) DEFAULT 'user', + `created` datetime NOT NULL, + `modified` datetime NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +``` + +Extending the Controller +------------------- + +You want to use one of your controllers to handle all the users features in your app, and keep the +login/register/etc actions from Users Plugin, + +First create a new controller class: + +```php + [ + // ... + // Controller used to manage users plugin features & actions + 'controller' => 'MyUsers', + // ... +``` + +Note you'll need to **copy the Plugin templates** you need into your project src/Template/MyUsers/[action].ctp + +Extending the Features in your controller +----------------------------- + +You could use a new Trait. For example, you want to add an 'impersonate' feature + +```php +getUsersTable()->find() + ->where(['id' => $userId]) + ->hydrate(false) + ->first(); + $this->Auth->setUser($user); + return $this->redirect('/'); + } +} +``` +Updating the Templates +------------------- + +Use the standard CakePHP conventions to override Plugin views using your application views +http://book.cakephp.org/3.0/en/plugins.html#overriding-plugin-templates-from-inside-your-application + +`{project_dir}/src/Template/Plugin/CakeDC/Users/Users/{templates_in_here}` + +Updating the Emails +------------------- + +Extend the `\CakeDC\Users\Mailer\UsersMailer` class and override the email configuration to change the way the +emails are sent by the Plugin. We currently have: +* validation, sent with a link to validate new users registered +* resetPassword, sent with a link to access the reset password feature +* socialAccountValidation, sent with a link to validate the social account used for login + +Example, to override the validation email you would need to: +* Create a new class in your application +```php +namespace App\Mailer; + +use Cake\Datasource\EntityInterface; +use CakeDC\Users\Mailer\UsersMailer; + +class MyUsersMailer extends UsersMailer +{ + public function resetPassword(EntityInterface $user) + { + parent::resetPassword($user); + $this->setSubject('This is the new subject'); + $this->setTemplate('custom-template-in-app-namespace'); + } +} +``` +* Configure the Plugin to use this new mailer class in bootstrap or users.php +`Configure::write('Users.Email.mailerClass', \App\Mailer\MyUsersMailer::class);` + +* Create the file `src/Template/Email/text/custom_template_in_app_namespace.ctp` +with your custom contents. Note you can also prepare an html version of the file, +change the template, or do any other customization in the `MyUsersMailer` method. + + diff --git a/Docs/Documentation/Google-Two-Factor-Authenticator.md b/Docs/Documentation/Google-Two-Factor-Authenticator.md new file mode 100644 index 000000000..99245ce76 --- /dev/null +++ b/Docs/Documentation/Google-Two-Factor-Authenticator.md @@ -0,0 +1,36 @@ +Google Two Factor Authenticator +=============================== + +Installation +------------ +To enable this feature you need to + +``` +composer require robthree/twofactorauth +``` + +Setup +----- + +Enable google authenticator in your bootstrap.php file: + +Config/bootstrap.php +``` +Configure::write('Users.GoogleAuthenticator.login', true); +``` + +How does it work +---------------- +When the user log-in, he is requested (image 1) to inform the current validation +code for your site in Google Authentation app (image 2), if this is the first +time he access he need to add your site to Google Authentation by reading +the QR code shown (image 1). + +1) Validation code page + + + +2) Google Authentation app + + + diff --git a/Docs/Documentation/GoogleAuthenticator/App.png b/Docs/Documentation/GoogleAuthenticator/App.png new file mode 100644 index 0000000000000000000000000000000000000000..dd47e98453d50c1aa3c68ed9195c272c5731daf3 GIT binary patch literal 52261 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�AN)pabKi!7 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 literal 0 HcmV?d00001 diff --git a/Docs/Documentation/GoogleAuthenticator/FirstLogin.png b/Docs/Documentation/GoogleAuthenticator/FirstLogin.png new file mode 100644 index 0000000000000000000000000000000000000000..18d4ce76e69dc9747ea629fe15e6d99ec1feefe5 GIT binary patch literal 21106 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 a6ZcZ8*^Y-HCTsshp^m2h#k}*@5B?853l{GH literal 0 HcmV?d00001 diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md new file mode 100644 index 000000000..bd8a34803 --- /dev/null +++ b/Docs/Documentation/Installation.md @@ -0,0 +1,115 @@ +Installation +============ + +Composer +------ + +``` +composer require cakedc/users +``` + +If you want to use social login features... + +``` +composer require league/oauth2-facebook:@stable +composer require league/oauth2-instagram:@stable +composer require league/oauth2-google:@stable +composer require league/oauth2-linkedin:@stable +composer require league/oauth1-client:@stable +``` + +NOTE: you'll need to enable social login in your bootstrap.php file if you want to use it, social +login is disabled by default. Check the [Configuration](Configuration.md#configuration-for-social-login) page for more details. + +``` +Configure::write('Users.Social.login', true); //to enable social login +``` + +If you want to use reCaptcha features... + +``` +composer require google/recaptcha:@stable +``` + +NOTE: you'll need to configure the reCaptcha key and secret, check the [Configuration](Configuration.md) +page for more details. + +If you want to use Google Authenticator features... + +``` +composer require robthree/twofactorauth:"^1.5.2" +``` + +NOTE: you'll need to enable `Users.GoogleAuthenticator.login` + +``` +Configure::write('Users.GoogleAuthenticator.login', true); +``` + +Load the Plugin +----------- + +Ensure the Users Plugin is loaded in your config/bootstrap.php file + +``` +Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); +``` + +Creating Required Tables +------------------------ +If you want to use the Users tables to store your users and social accounts: + +``` +bin/cake migrations migrate -p CakeDC/Users +``` + +Note you don't need to use the provided tables, you could customize the table names, fields etc in your +application and then use the plugin configuration to use your own tables instead. Please refer to the [Extending the Plugin](Extending-the-Plugin.md) +section to check all the customization options + +Customization +---------- + +config/bootstrap.php +``` +Configure::write('Users.config', ['users']); +Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); +Configure::write('Users.Social.login', true); //to enable social login +``` + +If you want to use social login, then in your config/users.php +``` +return [ + 'OAuth.providers.facebook.options.clientId' => 'YOUR APP ID', + 'OAuth.providers.facebook.options.clientSecret' => 'YOUR APP SECRET', + 'OAuth.providers.twitter.options.clientId' => 'YOUR APP ID', + 'OAuth.providers.twitter.options.clientSecret' => 'YOUR APP SECRET', + //etc +]; +``` +IMPORTANT: Remember you'll need to configure your social login application **callback url** to use the provider specific endpoint, for example: +* Facebook App Callback URL --> `http://yourdomain.com/auth/facebook` +* Twitter App Callback URL --> `http://yourdomain.com/auth/twitter` +* Google App Callback URL --> `http://yourdomain.com/auth/google` +* etc. + +Note: using social authentication is not required. + +For more details, check the Configuration doc page + +Load the UsersAuth Component +--------------------- + +Load the Component in your src/Controller/AppController.php, and use the passed Component configuration to customize the Users Plugin: + +``` + public function initialize() + { + parent::initialize(); + + // Important: add the 'enableBeforeRedirect' config or or disable deprecation warnings + $this->loadComponent('RequestHandler', ['enableBeforeRedirect' => false]); + $this->loadComponent('Flash'); + $this->loadComponent('CakeDC/Users.UsersAuth'); + } +``` diff --git a/Docs/Documentation/Migration/4.x-5.0.md b/Docs/Documentation/Migration/4.x-5.0.md new file mode 100644 index 000000000..9aba06bd3 --- /dev/null +++ b/Docs/Documentation/Migration/4.x-5.0.md @@ -0,0 +1,56 @@ +Migration 4.x to 5.0 +====================== + +5.0 is compatible with CakePHP ^3.4 and refactored some Auth objects into a new plugin +* Fix your Users configuration file, usually under `config/users.php` for Auth object references + +in `config/users.php` + +```php +$config = [ + // ... + 'Auth' => [ + // ... + 'authenticate' => [ + 'all' => [ + 'finder' => 'auth', + ], + 'CakeDC/Auth.ApiKey', + 'CakeDC/Auth.RememberMe', + 'Form', + ], + 'authorize' => [ + 'CakeDC/Auth.Superuser', + 'CakeDC/Auth.SimpleRbac', + ], + // ... +``` + +* Add a new configuration key to specify the controller name you are using to handle auth in your project + +in `config/users.php` + +```php +$config = [ + 'Users' => [ + // ... + // Controller used to manage users plugin features & actions + 'controller' => 'CakeDC/Users.Users', + // ... +``` + +* If you are using simple RBAC, set `CakeDC/Auth.SimpleRbac.permissions` configuration key to `null` if you want to load permissions from the file `config/permissions.php`. + +in `config/users.php` + +```php +$config = [ + 'Auth.authorize' => [ + 'CakeDC/Auth.SimpleRbac' => [ + 'autoload_config' => 'permissions', + 'permissions' => null, + ], + ], +``` + +If the value is false or empty array, now it is assumed there is no permissions for the user. \ No newline at end of file diff --git a/Docs/Documentation/Migration/6.x-7.0.md b/Docs/Documentation/Migration/6.x-7.0.md new file mode 100644 index 000000000..3258e398f --- /dev/null +++ b/Docs/Documentation/Migration/6.x-7.0.md @@ -0,0 +1,18 @@ +Migration 6.x to 7.0 +====================== + +7.0 is compatible with CakePHP ^3.6 and the plugin code was updated to remove all deprecations. + +* Add 'enableBeforeRedirect' configuration option to RequestHandler component load in your `src/Controller/AppController.php` file + +``` + public function initialize() + { + parent::initialize(); + + // Important: add the 'enableBeforeRedirect' config or or disable deprecation warnings + $this->loadComponent('RequestHandler', ['enableBeforeRedirect' => false]); + $this->loadComponent('Flash'); + $this->loadComponent('CakeDC/Users.UsersAuth'); + } +``` diff --git a/Docs/Documentation/Overview.md b/Docs/Documentation/Overview.md new file mode 100644 index 000000000..cc47d0159 --- /dev/null +++ b/Docs/Documentation/Overview.md @@ -0,0 +1,19 @@ +Overview +======== + +You can use the plugin as it comes if you're happy with it or, more common, extend your app specific user implementation from the plugin. + +The plugin itself is already capable of: + +* User registration +* Account verification by a token sent via email +* User login (email / password) +* Social login (Twitter, Facebook, Google, Instagram, LinkedIn) +* Password reset based on requesting a token by email and entering a new password +* User management (add / edit / delete) +* Simple roles management +* Simple Rbac and SuperUser Authorize +* RememberMe using cookie feature +* reCaptcha for user registration and login +* Two Factor authentication + diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md new file mode 100644 index 000000000..937039366 --- /dev/null +++ b/Docs/Documentation/SocialAuthenticate.md @@ -0,0 +1,97 @@ +SocialAuthenticate +============= + +We currently support the following providers to perform login as well as to link an existing account: + +* Facebook +* Twitter +* Google +* LinkedIn +* Instagram +* Amazon + +Please [contact us](https://cakedc.com/contact) if you need to support another provider. + +Setup +--------------------- + +Create the Facebook/Twitter applications you want to use and setup the configuration like this: + +Config/bootstrap.php +``` +Configure::write('OAuth.providers.facebook.options.clientId', 'YOUR APP ID'); +Configure::write('OAuth.providers.facebook.options.clientSecret', 'YOUR APP SECRET'); + +Configure::write('OAuth.providers.twitter.options.clientId', 'YOUR APP ID'); +Configure::write('OAuth.providers.twitter.options.clientSecret', 'YOUR APP SECRET'); +``` + +You can also change the default settings for social authenticate: + +``` +Configure::write('Users', [ + 'Email' => [ + //determines if the user should include email + 'required' => true, + //determines if registration workflow includes email validation + 'validate' => true, + ], + 'Social' => [ + //enable social login + 'login' => false, + ], + 'Key' => [ + 'Session' => [ + //session key to store the social auth data + 'social' => 'Users.social', + ], + //form key to store the social auth data + 'Form' => [ + 'social' => 'social' + ], + 'Data' => [ + //data key to store email coming from social networks + 'socialEmail' => 'info.email', + ], + ], +]); +``` + +If email is required and the social network does not return the user email then the user will be required to input the email. Additionally, validation could be enabled, in that case the user will be asked to validate the email before be able to login. There are some cases where the email address already exists onto database, if so, the user will receive an email and will be asked to validate the social account in the app. It is important to take into account that the user account itself will remain active and accessible by other ways (other social network account or username/password). + +In most situations you would not need to change any Oauth setting besides applications details. + +For new facebook aps you must use the graphApiVersion 2.8 or greater: + +``` +Configure::write('OAuth.providers.facebook.options.graphApiVersion', 'v2.8'); +``` + +User Helper +--------------------- + +You can use the helper included with the plugin to create Facebook/Twitter buttons: + +In templates +``` +$this->User->facebookLogin(); + +$this->User->twitterLogin(); +``` + +We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. + +Social Authentication was inspired by [UseMuffin/OAuth2](https://github.com/UseMuffin/OAuth2) library. + +Custom username field +--------------------- + +In your customized users table, add the SocialBehavior with the following configuration: + +```php +$this->addBehavior('CakeDC.Users/Social', [ + 'username' => 'email' +]); +``` + +By default it will use `username` field. diff --git a/Docs/Documentation/Translations.md b/Docs/Documentation/Translations.md new file mode 100644 index 000000000..41abc4e08 --- /dev/null +++ b/Docs/Documentation/Translations.md @@ -0,0 +1,17 @@ +Translations +============ + +The Plugin is translated into several languages: + +* Swedish (sv) by @digitalfotografen +* Spanish (es) by @florenciohernandez +* Brazillian Portuguese (pt_BR) by @andtxr +* French (fr_FR) by @jtraulle +* Polish (pl) by @joulbex +* Hungarian (hu_HU) by @rrd108 +* Italian (it) by @arturmamedov +* Turkish (tr_TR) by @sayinserdar + +**Note:** To overwrite the plugin translations, create a file inside your project 'src/Locale/{$lang}/' folder, with the name 'Users.po' and add the strings with the new translations. + +Remember to clean the translations cache! diff --git a/Docs/Documentation/UserHelper.md b/Docs/Documentation/UserHelper.md new file mode 100644 index 000000000..920f37f98 --- /dev/null +++ b/Docs/Documentation/UserHelper.md @@ -0,0 +1,85 @@ +UserHelper +============= + +The User Helper has some methods that may be needed if you want to improve your templates and add features to your app in an easy way. + +Setup +--------------- + +Enable the Helper in `src/view/AppView.php`: +```php +class AppView extends View +{ + public function initialize() + { + parent::initialize(); + $this->loadHelper('CakeDC/Users.User'); + } +} +``` + +Social Login +----------------- + +You can use the helper included with the plugin to create Facebook/Twitter buttons: + +In templates +```php +echo $this->User->socialLogin($provider); //provider is 'facebook', 'twitter', etc +``` + +We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. + +Connect Social Account +----------------- + +You can use the helper included with the plugin to create some 'Connect with Facebook/Twitter' buttons: + +In templates, call socialConnectLinkList method to get links for all social providers enabled +```php +echo $this->User->socialConnectLinkList($user->social_accounts); +``` + +We recommend the use of [Bootstrap Social](http://lipis.github.io/bootstrap-social/) in order to automatically apply styles to buttons. Anyway you can always add your own style to the buttons. + +The user must be allowed to access the urls "/link-social/[provider]" and "/callback-link-social/[provider]". + +Logout link +----------------- + +It allows to add a logout link anywhere in the app. + +```php +$this->User->logout(); +``` + +RBAC link +----------------- + +This function validates if you have access to a link and it displays it based on that. + +```php +$this->User->link(); +``` + +Welcome and profile link +----------------- + +It displays a welcome message for the user including the name and a link to the profile page + +```php +$this->User->welcome(); +``` + +reCaptcha +----------------- + +Handles the reCaptcha input display: + +```php +$this->User->addReCaptchaScript(); + +$this->User->addReCaptcha(); +``` + +Note reCaptcha script is added to script block when `addReCaptcha` method is called. diff --git a/Docs/Home.md b/Docs/Home.md new file mode 100644 index 000000000..378d61db9 --- /dev/null +++ b/Docs/Home.md @@ -0,0 +1,32 @@ +Home +==== + +The **Users** Plugin allow users to register and login, manage their profile, etc. It also allows admins to manage the users. + +The plugin is thought as a base to extend your app specific users controller and model from. + +That it works out of the box doesn't mean it is thought to be used exactly like it is but to provide you a kick start. + +Documentation +------------- + +* [Overview](Documentation/Overview.md) +* [Installation](Documentation/Installation.md) +* [Configuration](Documentation/Configuration.md) +* [SimpleRbacAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SimpleRbacAuthorize.md) +* [SuperuserAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SuperuserAuthorize.md) +* [ApiKeyAuthenticate](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/ApiKeyAuthenticate.md) +* [SocialAuthenticate](Documentation/SocialAuthenticate.md) +* [Google Authenticator](Documentation/Google-Two-Factor-Authenticator.md) +* [UserHelper](Documentation/UserHelper.md) +* [Events](Documentation/Events.md) +* [Extending the Plugin](Documentation/Extending-the-Plugin.md) +* [Translations](Documentation/Translations.md) + +Migration guides +---------------- + +* [4.x to 5.0](Documentation/Migration/4.x-5.0.md) +* [6.x to 7.0](Documentation/Migration/6.x-7.0.md) + + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..5448b2520 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,26 @@ +The MIT License + +Copyright 2009-2018 +Cake Development Corporation +1785 E. Sahara Avenue, Suite 490-423 +Las Vegas, Nevada 89104 +Phone: +1 702 425 5085 +https://www.cakedc.com + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 000000000..cc71ac418 --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +CakeDC Users Plugin +=================== + +[![Build Status](https://secure.travis-ci.org/CakeDC/users.png?branch=master)](http://travis-ci.org/CakeDC/users) +[![Coverage Status](https://img.shields.io/codecov/c/gh/CakeDC/users.svg?style=flat-square)](https://codecov.io/gh/CakeDC/users) +[![Downloads](https://poser.pugx.org/CakeDC/users/d/total.png)](https://packagist.org/packages/CakeDC/users) +[![Latest Version](https://poser.pugx.org/CakeDC/users/v/stable.png)](https://packagist.org/packages/CakeDC/users) +[![License](https://poser.pugx.org/CakeDC/users/license.svg)](https://packagist.org/packages/CakeDC/users) + +Versions and branches +--------------------- + +| CakePHP | CakeDC Users Plugin | Tag | Notes | +| :-------------: | :------------------------: | :--: | :---- | +| ^3.6 | [master](https://github.com/cakedc/users/tree/master) | 8.0.2 | stable | +| ^3.6 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | +| 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.3 | [4.x](https://github.com/cakedc/users/tree/4.x) | 4.2.0 | stable | +| 2.x | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.2.0 |stable | + +The **Users** plugin is back! + +It covers the following features: +* User registration +* Login/logout +* Social login (Facebook, Twitter, Instagram, Google, Linkedin, etc) +* Simple RBAC via https://github.com/CakeDC/auth +* Remember me (Cookie) via https://github.com/CakeDC/auth +* Manage user's profile +* Admin management + +The plugin is here to provide users related features following 2 approaches: +* Quick drop-in working solution for users login/registration. Get users working in 5 minutes. +* Extensible solution for a bigger/custom application. You'll be able to extend: + * UsersAuth Component + * Use your own UsersTable + * Use your own Controller + +On the previous versions of the plugin, extensibility was an issue, and one of the main +objectives of the 3.0 rewrite is to guarantee all the pieces could be extended/reused as +easily. + +Another decision made was limiting the plugin dependencies on other packages as much as possible. + +Requirements +------------ + +* CakePHP 3.6.0+ +* PHP 5.6+ + +Documentation +------------- + +For documentation, as well as tutorials, see the [Docs](Docs/Home.md) directory of this repository. + +Support +------- + +For bugs and feature requests, please use the [issues](https://github.com/CakeDC/users/issues) section of this repository. + +Commercial support is also available, [contact us](https://www.cakedc.com/contact) for more information. + +Contributing +------------ + +This repository follows the [CakeDC Plugin Standard](https://www.cakedc.com/plugin-standard). If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our [Contribution Guidelines](https://www.cakedc.com/contribution-guidelines) for detailed instructions. + +License +------- + +Copyright 2017 Cake Development Corporation (CakeDC). All rights reserved. + +Licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) License. Redistributions of the source code included in this repository must retain the copyright notice found in each file. diff --git a/config/Migrations/20150513201111_initial.php b/config/Migrations/20150513201111_initial.php new file mode 100644 index 000000000..55b00f094 --- /dev/null +++ b/config/Migrations/20150513201111_initial.php @@ -0,0 +1,152 @@ +table('users', ['id' => false, 'primary_key' => ['id']]); + $table + ->addColumn('id', 'uuid', [ + 'null' => false, + ]) + ->addColumn('username', 'string', [ + 'limit' => 255, + 'null' => false, + ]) + ->addColumn('email', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('password', 'string', [ + 'limit' => 255, + 'null' => false, + ]) + ->addColumn('first_name', 'string', [ + 'default' => null, + 'limit' => 50, + 'null' => true, + ]) + ->addColumn('last_name', 'string', [ + 'default' => null, + 'limit' => 50, + 'null' => true, + ]) + ->addColumn('token', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('token_expires', 'datetime', [ + 'default' => null, + 'null' => true, + ]) + ->addColumn('api_token', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('activation_date', 'datetime', [ + 'default' => null, + 'null' => true, + ]) + ->addColumn('tos_date', 'datetime', [ + 'default' => null, + 'null' => true, + ]) + ->addColumn('active', 'boolean', [ + 'default' => false, + 'null' => false, + ]) + ->addColumn('is_superuser', 'boolean', [ + 'default' => false, + 'null' => false, + ]) + ->addColumn('role', 'string', [ + 'default' => 'user', + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('created', 'datetime', [ + 'null' => false, + ]) + ->addColumn('modified', 'datetime', [ + 'null' => false, + ]) + ->create(); + + $table = $this->table('social_accounts', ['id' => false, 'primary_key' => ['id']]); + $table + ->addColumn('id', 'uuid', [ + 'null' => false, + ]) + ->addColumn('user_id', 'uuid', [ + 'null' => false, + ]) + ->addColumn('provider', 'string', [ + 'limit' => 255, + 'null' => false, + ]) + ->addColumn('username', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('reference', 'string', [ + 'limit' => 255, + 'null' => false, + ]) + ->addColumn('avatar', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => true, + ]) + ->addColumn('description', 'text', [ + 'default' => null, + 'null' => true, + ]) + ->addColumn('link', 'string', [ + 'limit' => 255, + 'null' => false, + ]) + ->addColumn('token', 'string', [ + 'limit' => 500, + 'null' => false, + ]) + ->addColumn('token_secret', 'string', [ + 'default' => null, + 'limit' => 500, + 'null' => true, + ]) + ->addColumn('token_expires', 'datetime', [ + 'default' => null, + 'null' => true, + ]) + ->addColumn('active', 'boolean', [ + 'default' => true, + 'null' => false, + ]) + ->addColumn('data', 'text', [ + 'null' => false, + ]) + ->addColumn('created', 'datetime', [ + 'null' => false, + ]) + ->addColumn('modified', 'datetime', [ + 'null' => false, + ]) + ->addForeignKey('user_id', 'users', 'id', array('delete' => 'CASCADE', 'update' => 'CASCADE')) + ->create(); + } +} diff --git a/config/Migrations/20161031101316_AddSecretToUsers.php b/config/Migrations/20161031101316_AddSecretToUsers.php new file mode 100644 index 000000000..27df2506c --- /dev/null +++ b/config/Migrations/20161031101316_AddSecretToUsers.php @@ -0,0 +1,43 @@ +table('users'); + /** + * Limiting secret field to 32 chars + * @see https://en.wikipedia.org/wiki/Google_Authenticator#Technical_description + */ + $table->addColumn('secret', 'string', [ + 'after' => 'activation_date', + 'default' => null, + 'limit' => 32, + 'null' => true, + ]); + $table->addColumn('secret_verified', 'boolean', [ + 'after' => 'secret', + 'default' => null, + 'null' => true, + ]); + $table->update(); + } +} diff --git a/config/Migrations/schema-dump-default.lock b/config/Migrations/schema-dump-default.lock new file mode 100644 index 0000000000000000000000000000000000000000..f4f542a7347d46742ad58d60b1b7e1b6ff262461 GIT binary patch literal 7938 zcmds6O>@&Q5aqY{$f;=wALGZ$zR*r0W9W$*%)3m47 z*;v}|eQzVhskn7wu@s3jnU+N=v&=MQ?UM8F;_Or;pX8Og_$+I=l1^Rx$bPAfy!a_s zg=+s##5+3SgGgSzewE^Dg-XsRPQ=HH_IsHrnoWsIB;Aeoag)yJ(VzB4B=w)lAB2CK zhD1)h6-lAW%lcPx{tb_iluc12=PPl7$9E#h)mk=1-HP#?naxI(cy{7MB=qOKNXU+# z{%|@3dRJCu+G$hLdw2ez#wnW~i$2h~vgTUn%94XVkh>xW!7Hw|y1ZmA(&BWvgoXEU zQ&Gse3tLmK-=~+VR2J!wX*zbEFP%VIt@VvU^t@+b33;}Z8(g-RC5u+6alj8`3DU-@ zwX&+r_BCZPcMoI=@<(2yzV}V8rw$3VmRz~a>Zl-cBA@=H5zl%+43RA6&#bl_ z;SEWFpVdIPN(3|f0DYW>-Xa#HDk8WOLESsLlZwxYE^ghJT(9-&Z}t6{3C10c ze_`A+JaT3|A{4LB?xMpwS)&NQyHy?co6b zLe~s>${}ub;0#@aaZdyaBpAc(-5p(ybBNkxrbLvb_S{Ieya@_aR&S*JLz%=Ch^3(g zbgU<+uq8e_ZwD=cm=Uv7uhv&7TAYNwa01*NxDqa08>{rCZ<=_DX;!!pAICN?z>GR5 z>!$-4Ve1_jPT$0bT2SX7sM=JN4#Bt5Wik)LBUgo*5C#4gxp&J5jYn-k0Urx+Jza)F zzm%o<{E_ZM6~Qhr7LW4U0F5{c1rBNKIjP!I#`+i$Q-q{9Y%h-6AJaFM*yDbBY@K!t z#CFh{9)fC)j!44uSVL%V|GmtZgfovbsYl?9=7@Cex3PY3KVxQ3U1Y7TtJ8;*`z2!l zPaPHXmqNY>OHd{=DA}mmpE@8%%wdo#veM~`@G`Q+LpncL({{R##};}P!+~L@vz_c@ z*34lOKxT93_}MA&LbP0%)agJC-|yM|S|Pnwc9I+cqD6Q*LZy%CVg$A}?)c&!XvR1d z@9QScYk}58auT5HtltQTLur?~rc#zLG69kQy298`J*2$F^5j3mBVS6bwSmqY=63^P zGJ!je{e16^#PgtA%*^RXxb>OrH)0ynhH(3P8cd*Qwup`G0D6SY1bC^(tW3sHAQKOP z6%+PYg$Z^{f3_j;lrS2@{D579ZFEF5VRpRV4xgxL^Q8ye(s$2Yhle)CUmSN5{*A7f rnO<>KjBXsHCzBF4-m>m!qeA-*2;i(8+m5hqdCYA`q}Jh<0e61^4bj5{ literal 0 HcmV?d00001 diff --git a/config/bootstrap.php b/config/bootstrap.php new file mode 100644 index 000000000..42d2bb0c2 --- /dev/null +++ b/config/bootstrap.php @@ -0,0 +1,49 @@ +each(function ($file) { + Configure::load($file); +}); + +TableRegistry::getTableLocator()->setConfig('Users', ['className' => Configure::read('Users.table')]); +TableRegistry::getTableLocator()->setConfig('CakeDC/Users.Users', ['className' => Configure::read('Users.table')]); + +if (Configure::check('Users.auth')) { + Configure::write('Auth.authenticate.all.userModel', Configure::read('Users.table')); +} + +if (Configure::read('Users.Social.login') && php_sapi_name() != 'cli') { + try { + EventManager::instance()->on(\CakeDC\Users\Controller\Component\UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, [new \CakeDC\Users\Controller\UsersController(), 'failedSocialLoginListener']); + } catch (MissingPluginException $e) { + Log::error($e->getMessage()); + } +} + +$oauthPath = Configure::read('OAuth.path'); +if (is_array($oauthPath)) { + Router::scope('/auth', function ($routes) use ($oauthPath) { + $routes->connect( + '/:provider', + $oauthPath, + ['provider' => implode('|', array_keys(Configure::read('OAuth.providers')))] + ); + }); +} diff --git a/config/permissions.php b/config/permissions.php new file mode 100644 index 000000000..79a4ae957 --- /dev/null +++ b/config/permissions.php @@ -0,0 +1,91 @@ + 'role' | ['roles'] | '*' + * 'prefix' => 'Prefix' | , (default = null) + * 'plugin' => 'Plugin' | , (default = null) + * 'controller' => 'Controller' | ['Controllers'] | '*', + * 'action' => 'action' | ['actions'] | '*', + * 'allowed' => true | false | callback (default = true) + * ] + * You could use '*' to match anything + * 'allowed' will be considered true if not defined. It allows a callable to manage complex + * permissions, like this + * 'allowed' => function (array $user, $role, Request $request) {} + * + * Example, using allowed callable to define permissions only for the owner of the Posts to edit/delete + * + * (remember to add the 'uses' at the top of the permissions.php file for Hash, TableRegistry and Request + [ + 'role' => ['user'], + 'controller' => ['Posts'], + 'action' => ['edit', 'delete'], + 'allowed' => function(array $user, $role, Request $request) { + $postId = Hash::get($request->params, 'pass.0'); + $post = TableRegistry::getTableLocator()->get('Posts')->get($postId); + $userId = Hash::get($user, 'id'); + if (!empty($post->user_id) && !empty($userId)) { + return $post->user_id === $userId; + } + return false; + } + ], + */ + +return [ + 'CakeDC/Auth.permissions' => [ + //admin role allowed to all the things + [ + 'role' => 'admin', + 'prefix' => '*', + 'extension' => '*', + 'plugin' => '*', + 'controller' => '*', + 'action' => '*', + ], + //specific actions allowed for the all roles in Users plugin + [ + 'role' => '*', + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => ['profile', 'logout', 'linkSocial', 'callbackLinkSocial'], + ], + [ + 'role' => '*', + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'resetGoogleAuthenticator', + 'allowed' => function (array $user, $role, \Cake\Http\ServerRequest $request) { + $userId = \Cake\Utility\Hash::get($request->getAttribute('params'), 'pass.0'); + if (!empty($userId) && !empty($user)) { + return $userId === $user['id']; + } + + return false; + } + ], + //all roles allowed to Pages/display + [ + 'role' => '*', + 'controller' => 'Pages', + 'action' => 'display', + ], + ] +]; diff --git a/config/routes.php b/config/routes.php new file mode 100644 index 000000000..f19f356a3 --- /dev/null +++ b/config/routes.php @@ -0,0 +1,52 @@ + '/users'], function ($routes) { + $routes->fallbacks('DashedRoute'); +}); + +Router::connect('/auth/twitter', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'twitterLogin', + 'provider' => 'twitter' +]); +Router::connect('/accounts/validate/*', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'SocialAccounts', + 'action' => 'validate' +]); +// Google Authenticator related routes +if (Configure::read('Users.GoogleAuthenticator.login')) { + Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']); + + Router::connect('/resetGoogleAuthenticator', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'resetGoogleAuthenticator' + ]); +} + +Router::connect('/profile/*', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); +Router::connect('/login', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); +Router::connect('/logout', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout']); +Router::connect('/link-social/*', [ + 'controller' => 'Users', + 'action' => 'linkSocial', + 'plugin' => 'CakeDC/Users', +]); +Router::connect('/callback-link-social/*', [ + 'controller' => 'Users', + 'action' => 'callbackLinkSocial', + 'plugin' => 'CakeDC/Users', +]); diff --git a/config/users.php b/config/users.php new file mode 100644 index 000000000..45a15f5ec --- /dev/null +++ b/config/users.php @@ -0,0 +1,206 @@ + [ + // Table used to manage users + 'table' => 'CakeDC/Users.Users', + // Controller used to manage users plugin features & actions + 'controller' => 'CakeDC/Users.Users', + // configure Auth component + 'auth' => true, + // Password Hasher + 'passwordHasher' => '\Cake\Auth\DefaultPasswordHasher', + // token expiration, 1 hour + 'Token' => ['expiration' => 3600], + 'Email' => [ + // determines if the user should include email + 'required' => true, + // determines if registration workflow includes email validation + 'validate' => true, + ], + 'Registration' => [ + // determines if the register is enabled + 'active' => true, + // determines if the reCaptcha is enabled for registration + 'reCaptcha' => true, + // allow a logged in user to access the registration form + 'allowLoggedIn' => false, + //ensure user is active (confirmed email) to reset his password + 'ensureActive' => false, + // default role name used in registration + 'defaultRole' => 'user', + ], + 'reCaptcha' => [ + // reCaptcha key goes here + 'key' => null, + // reCaptcha secret + 'secret' => null, + // use reCaptcha in registration + 'registration' => false, + // use reCaptcha in login, valid values are false, true + 'login' => false, + ], + 'Tos' => [ + // determines if the user should include tos accepted + 'required' => true, + ], + 'Social' => [ + // enable social login + 'login' => false, + // enable social login + 'authenticator' => 'CakeDC/Users.Social', + ], + 'GoogleAuthenticator' => [ + // enable Google Authenticator + 'login' => false, + 'issuer' => null, + // The number of digits the resulting codes will be + 'digits' => 6, + // The number of seconds a code will be valid + 'period' => 30, + // The algorithm used + 'algorithm' => 'sha1', + // QR-code provider (more on this later) + 'qrcodeprovider' => null, + // Random Number Generator provider (more on this later) + 'rngprovider' => null + ], + 'Profile' => [ + // Allow view other users profiles + 'viewOthers' => true, + 'route' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], + ], + 'Key' => [ + 'Session' => [ + // session key to store the social auth data + 'social' => 'Users.social', + // userId key used in reset password workflow + 'resetPasswordUserId' => 'Users.resetPasswordUserId', + ], + // form key to store the social auth data + 'Form' => [ + 'social' => 'social' + ], + 'Data' => [ + // data key to store the users email + 'email' => 'email', + // data key to store email coming from social networks + 'socialEmail' => 'info.email', + // data key to check if the remember me option is enabled + 'rememberMe' => 'remember_me', + ], + ], + // Avatar placeholder + 'Avatar' => ['placeholder' => 'CakeDC/Users.avatar_placeholder.png'], + 'RememberMe' => [ + // configure Remember Me component + 'active' => true, + 'checked' => true, + 'Cookie' => [ + 'name' => 'remember_me', + 'Config' => [ + 'expires' => '1 month', + 'httpOnly' => true, + ] + ] + ], + ], + 'GoogleAuthenticator' => [ + 'checker' => \CakeDC\Users\Auth\DefaultTwoFactorAuthenticationChecker::class, + 'verifyAction' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'verify', + 'prefix' => false, + ], + ], + // default configuration used to auto-load the Auth Component, override to change the way Auth works + 'Auth' => [ + 'loginAction' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + 'prefix' => false + ], + 'authenticate' => [ + 'all' => [ + 'finder' => 'auth', + ], + 'CakeDC/Auth.ApiKey', + 'CakeDC/Auth.RememberMe', + 'Form', + ], + 'authorize' => [ + 'CakeDC/Auth.Superuser', + 'CakeDC/Auth.SimpleRbac', + ], + ], + 'OAuth' => [ + 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'prefix' => null], + 'providers' => [ + 'facebook' => [ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.8', //bio field was deprecated on >= v2.8 + 'redirectUri' => Router::fullBaseUrl() . '/auth/facebook', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/facebook', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/facebook', + ] + ], + 'twitter' => [ + 'options' => [ + 'redirectUri' => Router::fullBaseUrl() . '/auth/twitter', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/twitter', + ] + ], + 'linkedIn' => [ + 'className' => 'League\OAuth2\Client\Provider\LinkedIn', + 'options' => [ + 'redirectUri' => Router::fullBaseUrl() . '/auth/linkedIn', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/linkedIn', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/linkedIn', + ] + ], + 'instagram' => [ + 'className' => 'League\OAuth2\Client\Provider\Instagram', + 'options' => [ + 'redirectUri' => Router::fullBaseUrl() . '/auth/instagram', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/instagram', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/instagram', + ] + ], + 'google' => [ + 'className' => 'League\OAuth2\Client\Provider\Google', + 'options' => [ + 'userFields' => ['url', 'aboutMe'], + 'redirectUri' => Router::fullBaseUrl() . '/auth/google', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/google', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/google', + ] + ], + 'amazon' => [ + 'className' => 'Luchianenco\OAuth2\Client\Provider\Amazon', + 'options' => [ + 'redirectUri' => Router::fullBaseUrl() . '/auth/amazon', + 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/amazon', + 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/amazon', + ] + ], + ], + ] +]; + +return $config; diff --git a/nbproject/project.properties b/nbproject/project.properties new file mode 100644 index 000000000..2babf34a9 --- /dev/null +++ b/nbproject/project.properties @@ -0,0 +1,7 @@ +include.path=${php.global.include.path} +php.version=PHP_70 +source.encoding=UTF-8 +src.dir=src +tags.asp=false +tags.short=false +web.root=. diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 000000000..33dfcdaa2 --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,9 @@ + + + org.netbeans.modules.php.project + + + users + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 000000000..500c19975 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,36 @@ + + + + + + + + + + + ./tests/TestCase + + + + + ./src + + + + + + + + + + + + diff --git a/src/Auth/DefaultTwoFactorAuthenticationChecker.php b/src/Auth/DefaultTwoFactorAuthenticationChecker.php new file mode 100644 index 000000000..be0c1843f --- /dev/null +++ b/src/Auth/DefaultTwoFactorAuthenticationChecker.php @@ -0,0 +1,44 @@ +isEnabled(); + } +} diff --git a/src/Auth/Exception/InvalidProviderException.php b/src/Auth/Exception/InvalidProviderException.php new file mode 100644 index 000000000..d19eee654 --- /dev/null +++ b/src/Auth/Exception/InvalidProviderException.php @@ -0,0 +1,31 @@ + 'id', + 'username' => 'username', + 'full_name' => 'name', + 'first_name' => 'first_name', + 'last_name' => 'last_name', + 'email' => 'email', + 'avatar' => 'avatar', + 'gender' => 'gender', + 'link' => 'link', + 'bio' => 'bio', + 'locale' => 'locale', + 'validated' => 'validated' + ]; + + /** + * Constructor + * + * @param mixed $rawData raw data + * @param mixed $mapFields map fields + */ + public function __construct($rawData, $mapFields = null) + { + $this->_rawData = $rawData; + if (!is_null($mapFields)) { + $this->_mapFields = $mapFields; + } + $this->_mapFields = array_merge($this->_defaultMapFields, $this->_mapFields); + } + /** + * Invoke method + * + * @return mixed + */ + public function __invoke() + { + return $this->_map(); + } + + /** + * If email is present the user is validated + * + * @return bool + */ + protected function _validated() + { + $email = Hash::get($this->_rawData, $this->_mapFields['email']); + + return !empty($email); + } + + /** + * Maps raw data using mapFields + * + * @return mixed + */ + protected function _map() + { + $result = []; + collection($this->_mapFields)->each(function ($mappedField, $field) use (&$result) { + $value = Hash::get($this->_rawData, $mappedField); + $function = '_' . $field; + if (method_exists($this, $function)) { + $value = $this->{$function}(); + } + $result[$field] = $value; + }); + + $token = Hash::get($this->_rawData, 'token'); + if (empty($token) || !(is_array($token) || $token instanceof \League\OAuth2\Client\Token\AccessToken)) { + return false; + } + $result['credentials'] = [ + 'token' => is_array($token) ? Hash::get($token, 'accessToken') : $token->getToken(), + 'secret' => is_array($token) ? Hash::get($token, 'tokenSecret') : null, + 'expires' => is_array($token) ? Hash::get($token, 'expires') : $token->getExpires(), + ]; + $result['raw'] = $this->_rawData; + + return $result; + } +} diff --git a/src/Auth/Social/Mapper/Amazon.php b/src/Auth/Social/Mapper/Amazon.php new file mode 100644 index 000000000..20c532052 --- /dev/null +++ b/src/Auth/Social/Mapper/Amazon.php @@ -0,0 +1,43 @@ + 'user_id' + ]; + + /** + * @return string + */ + protected function _link() + { + return self::AMAZON_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['id']); + } +} diff --git a/src/Auth/Social/Mapper/Facebook.php b/src/Auth/Social/Mapper/Facebook.php new file mode 100644 index 000000000..fbefa5010 --- /dev/null +++ b/src/Auth/Social/Mapper/Facebook.php @@ -0,0 +1,52 @@ + 'name', + ]; + + /** + * Get avatar url + * @return string + */ + protected function _avatar() + { + return self::FB_GRAPH_BASE_URL . Hash::get($this->_rawData, 'id') . '/picture?type=large'; + } + + /** + * @return string + */ + protected function _link() + { + return Hash::get($this->_rawData, 'link') ?: '#'; + } +} diff --git a/src/Auth/Social/Mapper/Google.php b/src/Auth/Social/Mapper/Google.php new file mode 100644 index 000000000..b895d5361 --- /dev/null +++ b/src/Auth/Social/Mapper/Google.php @@ -0,0 +1,43 @@ + 'image.url', + 'full_name' => 'displayName', + 'email' => 'emails.0.value', + 'first_name' => 'name.givenName', + 'last_name' => 'name.familyName', + 'bio' => 'aboutMe', + 'link' => 'url' + ]; + + /** + * @return string + */ + protected function _link() + { + return Hash::get($this->_rawData, $this->_mapFields['link']) ?: '#'; + } +} diff --git a/src/Auth/Social/Mapper/Instagram.php b/src/Auth/Social/Mapper/Instagram.php new file mode 100644 index 000000000..b6adecf1d --- /dev/null +++ b/src/Auth/Social/Mapper/Instagram.php @@ -0,0 +1,43 @@ + 'full_name', + 'avatar' => 'profile_picture', + ]; + + /** + * @return string + */ + protected function _link() + { + return self::INSTAGRAM_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['username']); + } +} diff --git a/src/Auth/Social/Mapper/LinkedIn.php b/src/Auth/Social/Mapper/LinkedIn.php new file mode 100644 index 000000000..cadda4b3c --- /dev/null +++ b/src/Auth/Social/Mapper/LinkedIn.php @@ -0,0 +1,28 @@ + 'pictureUrl', + 'first_name' => 'firstName', + 'last_name' => 'lastName', + 'email' => 'emailAddress', + 'bio' => 'headline', + 'link' => 'publicProfileUrl' + ]; +} diff --git a/src/Auth/Social/Mapper/Pinterest.php b/src/Auth/Social/Mapper/Pinterest.php new file mode 100644 index 000000000..d1b630b73 --- /dev/null +++ b/src/Auth/Social/Mapper/Pinterest.php @@ -0,0 +1,24 @@ + 'image.60x60.url', + 'link' => 'url', + ]; +} diff --git a/src/Auth/Social/Mapper/Tumblr.php b/src/Auth/Social/Mapper/Tumblr.php new file mode 100644 index 000000000..2f18418a8 --- /dev/null +++ b/src/Auth/Social/Mapper/Tumblr.php @@ -0,0 +1,46 @@ + 'uid', + 'username' => 'nickname', + 'full_name' => 'name', + 'first_name' => 'firstName', + 'last_name' => 'lastName', + 'email' => 'email', + 'avatar' => 'imageUrl', + 'bio' => 'extra.blogs.0.description', + 'validated' => 'validated', + 'link' => 'extra.blogs.0.url' + ]; + + /** + * @return string + */ + protected function _id() + { + return crc32($this->_rawData['nickname']); + } +} diff --git a/src/Auth/Social/Mapper/Twitter.php b/src/Auth/Social/Mapper/Twitter.php new file mode 100644 index 000000000..3dccfa45f --- /dev/null +++ b/src/Auth/Social/Mapper/Twitter.php @@ -0,0 +1,59 @@ + 'uid', + 'username' => 'nickname', + 'full_name' => 'name', + 'first_name' => 'firstName', + 'last_name' => 'lastName', + 'email' => 'email', + 'avatar' => 'imageUrl', + 'bio' => 'description', + 'validated' => 'validated' + ]; + + /** + * @return string + */ + protected function _link() + { + return self::TWITTER_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['username']); + } + + /** + * @return string + */ + protected function _avatar() + { + return str_replace('normal', 'bigger', Hash::get($this->_rawData, $this->_mapFields['avatar'])); + } +} diff --git a/src/Auth/Social/Util/SocialUtils.php b/src/Auth/Social/Util/SocialUtils.php new file mode 100644 index 000000000..0ae12fbf1 --- /dev/null +++ b/src/Auth/Social/Util/SocialUtils.php @@ -0,0 +1,35 @@ +getShortName(); + } +} diff --git a/src/Auth/SocialAuthenticate.php b/src/Auth/SocialAuthenticate.php new file mode 100755 index 000000000..a5602c150 --- /dev/null +++ b/src/Auth/SocialAuthenticate.php @@ -0,0 +1,488 @@ +_isProviderEnabled($oauthConfig['providers']['twitter']); + //We unset twitter from providers to exclude from OAuth2 config + unset($oauthConfig['providers']['twitter']); + + $providers = []; + foreach ($oauthConfig['providers'] as $provider => $options) { + if ($this->_isProviderEnabled($options)) { + $providers[$provider] = $options; + } + } + $oauthConfig['providers'] = $providers; + Configure::write('OAuth2', $oauthConfig); + $config = $this->normalizeConfig(Hash::merge($config, $oauthConfig), $enabledNoOAuth2Provider); + parent::__construct($registry, $config); + } + + /** + * Normalizes providers' configuration. + * + * @param array $config Array of config to normalize. + * @param bool $enabledNoOAuth2Provider True when any noOAuth2 provider is enabled + * @return array + * @throws \Exception + */ + public function normalizeConfig(array $config, $enabledNoOAuth2Provider = false) + { + $config = Hash::merge((array)Configure::read('OAuth2'), $config); + + if (empty($config['providers']) && !$enabledNoOAuth2Provider) { + throw new MissingProviderConfigurationException(); + } + + if (!empty($config['providers'])) { + array_walk($config['providers'], [$this, '_normalizeConfig'], $config); + } + + return $config; + } + + /** + * Callback to loop through config values. + * + * @param array $config Configuration. + * @param string $alias Provider's alias (key) in configuration. + * @param array $parent Parent configuration. + * @return void + */ + protected function _normalizeConfig(&$config, $alias, $parent) + { + unset($parent['providers']); + + $defaults = [ + 'className' => null, + 'options' => [], + 'collaborators' => [], + 'mapFields' => [], + ] + $parent + $this->_defaultConfig; + + $config = array_intersect_key($config, $defaults); + $config += $defaults; + + array_walk($config, [$this, '_validateConfig']); + + foreach (['options', 'collaborators'] as $key) { + if (empty($parent[$key]) || empty($config[$key])) { + continue; + } + + $config[$key] = array_merge($parent[$key], $config[$key]); + } + } + + /** + * Validates the configuration. + * + * @param mixed $value Value. + * @param string $key Key. + * @return void + * @throws \CakeDC\Users\Auth\Exception\InvalidProviderException + * @throws \CakeDC\Users\Auth\Exception\InvalidSettingsException + */ + protected function _validateConfig(&$value, $key) + { + if ($key === 'className' && !class_exists($value)) { + throw new InvalidProviderException([$value]); + } elseif (!is_array($value) && in_array($key, ['options', 'collaborators'])) { + throw new InvalidSettingsException([$key]); + } + } + + /** + * Get the controller associated with the collection. + * + * @return \Cake\Controller\Controller Controller instance + */ + protected function _getController() + { + return $this->_registry->getController(); + } + + /** + * Returns when a provider has been enabled. + * + * @param array $options array of options by provider + * @return bool + */ + protected function _isProviderEnabled($options) + { + return !empty($options['options']['redirectUri']) && !empty($options['options']['clientId']) && + !empty($options['options']['clientSecret']); + } + + /** + * Get a user based on information in the request. + * + * @param \Cake\Http\ServerRequest $request Request object. + * @param \Cake\Http\Response $response Response object. + * @return bool + * @throws \RuntimeException If the `CakeDC/Users/OAuth2.newUser` event is missing or returns empty. + */ + public function authenticate(ServerRequest $request, Response $response) + { + return $this->getUser($request); + } + + /** + * Authenticates with OAuth2 provider by getting an access token and + * retrieving the authorized user's profile data. + * + * @param \Cake\Http\ServerRequest $request Request object. + * @return array|bool + */ + protected function _authenticate(ServerRequest $request) + { + if (!$this->_validate($request)) { + return false; + } + + $provider = $this->provider($request); + $code = $request->getQuery('code'); + + try { + $token = $provider->getAccessToken('authorization_code', compact('code')); + + return compact('token') + $provider->getResourceOwner($token)->toArray(); + } catch (\Exception $e) { + $message = sprintf( + "Error getting an access token / retrieving the authorized user's profile data. Error message: %s %s", + $e->getMessage(), + $e + ); + $this->log($message); + + return false; + } + } + + /** + * Validates OAuth2 request. + * + * @param \Cake\Http\ServerRequest $request Request object. + * @return bool + */ + protected function _validate(ServerRequest $request) + { + if (!array_key_exists('code', $request->getQueryParams()) || !$this->provider($request)) { + return false; + } + + $session = $request->getSession(); + $sessionKey = 'oauth2state'; + $state = $request->getQuery('state'); + + if ($this->getConfig('options.state') && + (!$state || $state !== $session->read($sessionKey))) { + $session->delete($sessionKey); + + return false; + } + + return true; + } + + /** + * Maps raw provider's user profile data to local user's data schema. + * + * @param array $data Raw user data. + * @return array + */ + protected function _map($data) + { + if (!$map = $this->getConfig('mapFields')) { + return $data; + } + + foreach ($map as $dst => $src) { + $data[$dst] = $data[$src]; + unset($data[$src]); + } + + return $data; + } + + /** + * Handles unauthenticated access attempts. Will automatically forward to the + * requested provider's authorization URL to let the user grant access to the + * application. + * + * @param \Cake\Http\ServerRequest $request Request object. + * @param \Cake\Http\Response $response Response object. + * @return \Cake\Http\Response|null + */ + public function unauthenticated(ServerRequest $request, Response $response) + { + $provider = $this->provider($request); + if (empty($provider) || !empty($request->getQuery('code'))) { + return null; + } + + if ($this->getConfig('options.state')) { + $request->getSession()->write('oauth2state', $provider->getState()); + } + + $response = $response->withLocation($provider->getAuthorizationUrl()); + + return $response; + } + + /** + * Returns the `$request`-ed provider. + * + * @param \Cake\Http\ServerRequest $request Current HTTP request. + * @return \League\Oauth2\Client\Provider\GenericProvider|false + */ + public function provider(ServerRequest $request) + { + if (!$alias = $request->getParam('provider')) { + return false; + } + + if (empty($this->_provider)) { + $this->_provider = $this->_getProvider($alias); + } + + return $this->_provider; + } + + /** + * Instantiates provider object. + * + * @param string $alias of the provider. + * @return \League\Oauth2\Client\Provider\GenericProvider + */ + protected function _getProvider($alias) + { + if (!$config = $this->getConfig('providers.' . $alias)) { + return false; + } + + $this->setConfig($config); + + if (is_object($config) && $config instanceof AbstractProvider) { + return $config; + } + + $class = $config['className']; + + return new $class($config['options'], $config['collaborators']); + } + + /** + * Find or create local user + * + * @param array $data data + * @return array|bool|mixed + * @throws MissingEmailException + */ + protected function _touch(array $data) + { + try { + if (empty($data['provider']) && !empty($this->_provider)) { + $data['provider'] = SocialUtils::getProvider($this->_provider); + } + $user = $this->_socialLogin($data); + } catch (UserNotActiveException $ex) { + $exception = $ex; + } catch (AccountNotActiveException $ex) { + $exception = $ex; + } catch (MissingEmailException $ex) { + $exception = $ex; + } + if (!empty($exception)) { + $args = ['exception' => $exception, 'rawData' => $data]; + $this->_getController()->dispatchEvent(UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN, $args); + if (method_exists($this->_getController(), 'failedSocialLogin')) { + $this->_getController()->failedSocialLogin($exception, $data, true); + } + + return false; + } + + // If new SocialAccount was created $user is returned containing it + if ($user->get('social_accounts')) { + $this->_getController()->dispatchEvent(UsersAuthComponent::EVENT_AFTER_REGISTER, compact('user')); + } + + if (!empty($user->username)) { + $user = $this->_findUser($user->username); + } + + return $user; + } + + /** + * Get a user based on information in the request. + * + * @param \Cake\Http\ServerRequest $request Request object. + * @return mixed Either false or an array of user information + * @throws \RuntimeException If the `CakeDC/Users/OAuth2.newUser` event is missing or returns empty. + */ + public function getUser(ServerRequest $request) + { + $data = $request->getSession()->read(Configure::read('Users.Key.Session.social')); + $requestDataEmail = $request->getData('email'); + if (!empty($data) && empty($data['uid']) && (!empty($data['email']) || !empty($requestDataEmail))) { + if (!empty($requestDataEmail)) { + $data['email'] = $requestDataEmail; + } + $user = $data; + $request->getSession()->delete(Configure::read('Users.Key.Session.social')); + } else { + if (empty($data) && !$rawData = $this->_authenticate($request)) { + return false; + } + if (empty($rawData)) { + $rawData = $data; + } + + $provider = $this->_getProviderName($request); + try { + $user = $this->_mapUser($provider, $rawData); + if ($this->_getController()->components()->has('Auth')) { + $this->_getController()->Auth->setConfig('authError', false); + } + } catch (MissingProviderException $ex) { + $request->getSession()->delete(Configure::read('Users.Key.Session.social')); + throw $ex; + } + if ($user['provider'] === SocialAccountsTable::PROVIDER_TWITTER) { + $request->getSession()->write(Configure::read('Users.Key.Session.social'), $user); + } + } + + if (!$user || !$this->getConfig('userModel')) { + return false; + } + + if (!$result = $this->_touch($user)) { + return false; + } + + if ($request->getSession()->check(Configure::read('Users.Key.Session.social'))) { + $request->getSession()->delete(Configure::read('Users.Key.Session.social')); + } + $request->getSession()->write('Users.successSocialLogin', true); + + return $result; + } + + /** + * Get the provider name based on the request or on the provider set. + * + * @param \Cake\Http\ServerRequest $request Request object. + * @return mixed Either false or an array of user information + */ + protected function _getProviderName($request = null) + { + $provider = false; + if (!empty($request->getParam('provider'))) { + $provider = ucfirst($request->getParam('provider')); + } elseif (!is_null($this->_provider)) { + $provider = SocialUtils::getProvider($this->_provider); + } + + return $provider; + } + + /** + * Get the provider name based on the request or on the provider set. + * + * @param string $provider Provider name. + * @param array $data User data + * @throws MissingProviderException + * @return mixed Either false or an array of user information + */ + protected function _mapUser($provider, $data) + { + if (empty($provider)) { + throw new MissingProviderException(__d('CakeDC/Users', "Provider cannot be empty")); + } + $providerMapperClass = $this->getConfig('providers.' . strtolower($provider) . '.options.mapper') ?: "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$provider"; + $providerMapper = new $providerMapperClass($data); + $user = $providerMapper(); + $user['provider'] = $provider; + + return $user; + } + + /** + * @param mixed $data data + * @return mixed + */ + protected function _socialLogin($data) + { + $options = [ + 'use_email' => Configure::read('Users.Email.required'), + 'validate_email' => Configure::read('Users.Email.validate'), + 'token_expiration' => Configure::read('Users.Token.expiration') + ]; + + $userModel = Configure::read('Users.table'); + $User = TableRegistry::getTableLocator()->get($userModel); + $user = $User->socialLogin($data, $options); + + return $user; + } +} diff --git a/src/Auth/TwoFactorAuthenticationCheckerFactory.php b/src/Auth/TwoFactorAuthenticationCheckerFactory.php new file mode 100644 index 000000000..8287fdf1d --- /dev/null +++ b/src/Auth/TwoFactorAuthenticationCheckerFactory.php @@ -0,0 +1,39 @@ +loadComponent('Security'); + if ($this->request->getParam('_csrfToken') === false) { + $this->loadComponent('Csrf'); + } + $this->loadComponent('CakeDC/Users.UsersAuth'); + } +} diff --git a/src/Controller/Component/GoogleAuthenticatorComponent.php b/src/Controller/Component/GoogleAuthenticatorComponent.php new file mode 100644 index 000000000..215e96853 --- /dev/null +++ b/src/Controller/Component/GoogleAuthenticatorComponent.php @@ -0,0 +1,84 @@ +tfa = new TwoFactorAuth( + Configure::read('Users.GoogleAuthenticator.issuer'), + Configure::read('Users.GoogleAuthenticator.digits'), + Configure::read('Users.GoogleAuthenticator.period'), + Configure::read('Users.GoogleAuthenticator.algorithm'), + Configure::read('Users.GoogleAuthenticator.qrcodeprovider'), + Configure::read('Users.GoogleAuthenticator.rngprovider') + ); + } + } + + /** + * createSecret + * @return string base32 shared secret stored in users table + */ + public function createSecret() + { + return $this->tfa->createSecret(); + } + + /** + * verifyCode + * Verifying tfa code with shared secret + * @param string $secret of the user + * @param string $code from verification form + * @return bool + */ + public function verifyCode($secret, $code) + { + return $this->tfa->verifyCode($secret, $code); + } + + /** + * getQRCodeImageAsDataUri + * @param string $issuer issuer + * @param string $secret secret + * @return string base64 string containing QR code for shared secret + */ + public function getQRCodeImageAsDataUri($issuer, $secret) + { + return $this->tfa->getQRCodeImageAsDataUri($issuer, $secret); + } +} diff --git a/src/Controller/Component/RememberMeComponent.php b/src/Controller/Component/RememberMeComponent.php new file mode 100644 index 000000000..742d91b63 --- /dev/null +++ b/src/Controller/Component/RememberMeComponent.php @@ -0,0 +1,159 @@ +_cookieName = Configure::read('Users.RememberMe.Cookie.name'); + $this->_validateConfig(); + $this->setCookieOptions(); + $this->_attachEvents(); + } + + /** + * Validate component config + * + * @throws InvalidArgumentException + * @return void + */ + protected function _validateConfig() + { + if (mb_strlen(Security::getSalt(), '8bit') < 32) { + throw new InvalidArgumentException( + __d('CakeDC/Users', 'Invalid app salt, app salt must be at least 256 bits (32 bytes) long') + ); + } + } + + /** + * Attach the afterLogin and beforeLogount events + * + * @return void + */ + protected function _attachEvents() + { + $eventManager = $this->getController()->getEventManager(); + $eventManager->on(UsersAuthComponent::EVENT_AFTER_LOGIN, [], [$this, 'setLoginCookie']); + $eventManager->on(UsersAuthComponent::EVENT_BEFORE_LOGOUT, [], [$this, 'destroy']); + } + + /** + * Sets cookie configuration options + * + * @return void + */ + public function setCookieOptions() + { + $cookieConfig = Configure::read('Users.RememberMe.Cookie.Config'); + $this->Cookie->configKey($this->_cookieName, $cookieConfig); + } + + /** + * Sets the login cookie that handles the remember me feature + * + * @param Event $event event + * @return void + */ + public function setLoginCookie(Event $event) + { + $user['id'] = $this->Auth->user('id'); + if (empty($user)) { + return; + } + $user['user_agent'] = $this->getController()->getRequest()->getHeaderLine('User-Agent'); + if (!(bool)$this->getController()->getRequest()->getData(Configure::read('Users.Key.Data.rememberMe'))) { + return; + } + $this->Cookie->write($this->_cookieName, $user); + } + + /** + * Destroys the remember me cookie + * + * @param Event $event event + * @return void + */ + public function destroy(Event $event) + { + if ($this->Cookie->check($this->_cookieName)) { + $this->Cookie->delete($this->_cookieName); + } + } + + /** + * Reads the stored cookie and auto login the user if present + * + * @param Event $event event + * @return mixed + */ + public function beforeFilter(Event $event) + { + $user = $this->Auth->user(); + if (!empty($user) || + $this->getController()->getRequest()->is(['post', 'put']) || + $this->getController()->getRequest()->getParam('action') === 'logout' || + $this->getController()->getRequest()->getSession()->check(Configure::read('Users.Key.Session.social')) || + $this->getController()->getRequest()->getParam('provider')) { + return; + } + + $user = $this->Auth->identify(); + // No user no cookies + if (empty($user)) { + return; + } + $this->Auth->setUser($user); + $event = $this->getController()->dispatchEvent(UsersAuthComponent::EVENT_AFTER_COOKIE_LOGIN); + if (is_array($event->result)) { + return $this->getController()->redirect($event->result); + } + $url = $this->getController()->getRequest()->getRequestTarget(); + + return $this->getController()->redirect($url); + } +} diff --git a/src/Controller/Component/SetupComponent.php b/src/Controller/Component/SetupComponent.php new file mode 100644 index 000000000..dc20cb060 --- /dev/null +++ b/src/Controller/Component/SetupComponent.php @@ -0,0 +1,33 @@ +getController()->loadComponent('CakeDC/Users.UsersAuth'); + list($plugin, $controller) = pluginSplit(Configure::read('Users.controller')); + if ($this->getController()->getRequest()->getParam('plugin', null) === $plugin && + $this->getController()->getRequest()->getParam('controller') === $controller + ) { + $this->getController()->Auth->allow(['login']); + } + } +} diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php new file mode 100644 index 000000000..92fa56e7d --- /dev/null +++ b/src/Controller/Component/UsersAuthComponent.php @@ -0,0 +1,247 @@ +_validateConfig(); + $this->_initAuth(); + + if (Configure::read('Users.Social.login')) { + $this->_loadSocialLogin(); + } + if (Configure::read('Users.RememberMe.active')) { + $this->_loadRememberMe(); + } + + if ($this->getTwoFactorAuthenticationChecker()->isEnabled()) { + $this->_loadGoogleAuthenticator(); + } + + $this->_attachPermissionChecker(); + } + + /** + * Load GoogleAuthenticator object + * + * @return void + */ + protected function _loadGoogleAuthenticator() + { + $this->getController()->loadComponent('CakeDC/Users.GoogleAuthenticator'); + } + + /** + * Load Social Auth object + * + * @return void + */ + protected function _loadSocialLogin() + { + $this->getController()->Auth->setConfig('authenticate', [ + Configure::read('Users.Social.authenticator') + ], true); + } + + /** + * Load RememberMe component and Auth objects + * + * @return void + */ + protected function _loadRememberMe() + { + $this->getController()->loadComponent('CakeDC/Users.RememberMe'); + } + + /** + * Attach the isUrlAuthorized event to allow using the Auth authorize from the UserHelper + * + * @return void + */ + protected function _attachPermissionChecker() + { + EventManager::instance()->on(self::EVENT_IS_AUTHORIZED, [], [$this, 'isUrlAuthorized']); + } + + /** + * Initialize the AuthComponent and configure allowed actions + * + * @return void + */ + protected function _initAuth() + { + if (Configure::read('Users.auth')) { + //initialize Auth + $this->getController()->loadComponent('Auth', Configure::read('Auth')); + } + + list($plugin, $controller) = pluginSplit(Configure::read('Users.controller')); + if ($this->getController()->getRequest()->getParam('plugin', null) === $plugin && + $this->getController()->getRequest()->getParam('controller') === $controller + ) { + $this->getController()->Auth->allow([ + // LoginTrait + 'twitterLogin', + 'login', + 'socialEmail', + 'verify', + // RegisterTrait + 'register', + 'validateEmail', + // PasswordManagementTrait used in RegisterTrait + 'changePassword', + 'resetPassword', + 'requestResetPassword', + // UserValidationTrait used in PasswordManagementTrait + 'resendTokenValidation', + // Social + 'endpoint', + 'authenticated', + ]); + } + } + + /** + * Check if a given url is authorized + * + * @param Event $event event + * + * @return bool + */ + public function isUrlAuthorized(Event $event) + { + $url = Hash::get((array)$event->getData(), 'url'); + if (empty($url)) { + return false; + } + + if (is_array($url)) { + $requestUrl = Router::normalize(Router::reverse($url)); + $requestParams = Router::parseRequest(new ServerRequest($requestUrl)); + } else { + try { + //remove base from $url if exists + $normalizedUrl = Router::normalize($url); + $requestParams = Router::parseRequest(new ServerRequest($normalizedUrl)); + } catch (MissingRouteException $ex) { + //if it's a url pointing to our own app + if (substr($normalizedUrl, 0, 1) === '/') { + throw $ex; + } + + return true; + } + $requestUrl = $url; + } + // check if controller action is allowed + if ($this->_isActionAllowed($requestParams)) { + return true; + } + + // check we are logged in + $user = $this->getController()->Auth->user(); + if (empty($user)) { + return false; + } + + $request = new ServerRequest($requestUrl); + $request = $request->withAttribute('params', $requestParams); + + $isAuthorized = $this->getController()->Auth->isAuthorized(null, $request); + + return $isAuthorized; + } + + /** + * Validate if the passed configuration makes sense + * + * @throws BadConfigurationException + * @return void + */ + protected function _validateConfig() + { + if (!Configure::read('Users.Email.required') && Configure::read('Users.Email.validate')) { + $message = __d('CakeDC/Users', 'You can\'t enable email validation workflow if use_email is false'); + throw new BadConfigurationException($message); + } + } + + /** + * Check if the action is in allowedActions array for the controller + * Important, this function will check only for allowed actions in the current + * controller, creating a new instance and providing initialization for the Auth + * instance in another controller could lead to undesired side effects. + * + * @param array $requestParams request parameters + * @return bool + */ + protected function _isActionAllowed($requestParams = []) + { + if (empty($requestParams['action'])) { + return false; + } + if (!empty($requestParams['controller']) && $requestParams['controller'] !== $this->getController()->getName()) { + return false; + } + $action = strtolower($requestParams['action']); + if (in_array($action, array_map('strtolower', $this->getController()->Auth->allowedActions))) { + return true; + } + + return false; + } + + /** + * Get the configured two factory authentication + * + * @return \CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface + */ + protected function getTwoFactorAuthenticationChecker() + { + return (new TwoFactorAuthenticationCheckerFactory())->build(); + } +} diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php new file mode 100644 index 000000000..b22507464 --- /dev/null +++ b/src/Controller/SocialAccountsController.php @@ -0,0 +1,94 @@ +Auth->allow(['validateAccount', 'resendValidation']); + } + + /** + * Validates social account + * + * @param string $provider provider + * @param string $reference reference + * @param string $token token + * @return Response + */ + public function validateAccount($provider, $reference, $token) + { + try { + $result = $this->SocialAccounts->validateAccount($provider, $reference, $token); + if ($result) { + $this->Flash->success(__d('CakeDC/Users', 'Account validated successfully')); + } else { + $this->Flash->error(__d('CakeDC/Users', 'Account could not be validated')); + } + } catch (RecordNotFoundException $exception) { + $this->Flash->error(__d('CakeDC/Users', 'Invalid token and/or social account')); + } catch (AccountAlreadyActiveException $exception) { + $this->Flash->error(__d('CakeDC/Users', 'Social Account already active')); + } catch (\Exception $exception) { + $this->Flash->error(__d('CakeDC/Users', 'Social Account could not be validated')); + } + + return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + } + + /** + * Resends validation email if required + * + * @param string $provider provider + * @param string $reference reference + * @return mixed + * @throws AccountAlreadyActiveException + */ + public function resendValidation($provider, $reference) + { + try { + $result = $this->SocialAccounts->resendValidation($provider, $reference); + if ($result) { + $this->Flash->success(__d('CakeDC/Users', 'Email sent successfully')); + } else { + $this->Flash->error(__d('CakeDC/Users', 'Email could not be sent')); + } + } catch (RecordNotFoundException $exception) { + $this->Flash->error(__d('CakeDC/Users', 'Invalid account')); + } catch (AccountAlreadyActiveException $exception) { + $this->Flash->error(__d('CakeDC/Users', 'Social Account already active')); + } catch (\Exception $exception) { + $this->Flash->error(__d('CakeDC/Users', 'Email could not be resent')); + } + + return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + } +} diff --git a/src/Controller/Traits/CustomUsersTableTrait.php b/src/Controller/Traits/CustomUsersTableTrait.php new file mode 100644 index 000000000..f016f66de --- /dev/null +++ b/src/Controller/Traits/CustomUsersTableTrait.php @@ -0,0 +1,51 @@ +_usersTable instanceof Table) { + return $this->_usersTable; + } + $this->_usersTable = TableRegistry::getTableLocator()->get(Configure::read('Users.table')); + + return $this->_usersTable; + } + + /** + * Set the users table + * + * @param Table $table table + * @return void + */ + public function setUsersTable(Table $table) + { + $this->_usersTable = $table; + } +} diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php new file mode 100644 index 000000000..9b10c960b --- /dev/null +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -0,0 +1,237 @@ +_getSocialProvider($alias); + + $temporaryCredentials = []; + if (ucfirst($alias) === SocialAccountsTable::PROVIDER_TWITTER) { + $temporaryCredentials = $provider->getTemporaryCredentials(); + $this->request->getSession()->write('temporary_credentials', $temporaryCredentials); + } + $authUrl = $provider->getAuthorizationUrl($temporaryCredentials); + if (empty($temporaryCredentials)) { + $this->request->session()->write('SocialLink.oauth2state', $provider->getState()); + } + + return $this->redirect($authUrl); + } + + /** + * Callback to get user information from provider + * + * @param string $alias of the provider. + * + * @throws \Cake\Http\Exception\NotFoundException Quando o provider informado nĆ£o existe + * @return \Cake\Http\Response Redirects to profile if okay or error + */ + public function callbackLinkSocial($alias = null) + { + $message = __d('CakeDC/Users', 'Could not associate account, please try again.'); + $provider = $this->_getSocialProvider($alias); + $error = false; + if (ucfirst($alias) === SocialAccountsTable::PROVIDER_TWITTER) { + $server = new Twitter([ + 'identifier' => Configure::read('OAuth.providers.twitter.options.clientId'), + 'secret' => Configure::read('OAuth.providers.twitter.options.clientSecret'), + 'callbackUri' => Configure::read('OAuth.providers.twitter.options.callbackLinkSocialUri'), + ]); + $oauthToken = $this->request->getQuery('oauth_token'); + $oauthVerifier = $this->request->getQuery('oauth_verifier'); + if (!empty($oauthToken) && !empty($oauthVerifier)) { + $temporaryCredentials = $this->request->getSession()->read('temporary_credentials'); + try { + $tokenCredentials = $server->getTokenCredentials($temporaryCredentials, $oauthToken, $oauthVerifier); + $data = (array)$server->getUserDetails($tokenCredentials); + $data['token'] = [ + 'accessToken' => $tokenCredentials->getIdentifier(), + 'tokenSecret' => $tokenCredentials->getSecret(), + ]; + } catch (\Exception $e) { + $error = $e; + } + } + } else { + if (!$this->_validateCallbackSocialLink()) { + $this->Flash->error($message); + + return $this->redirect(['action' => 'profile']); + } + $code = $this->request->getQuery('code'); + try { + $token = $provider->getAccessToken('authorization_code', compact('code')); + + $data = compact('token') + $provider->getResourceOwner($token)->toArray(); + } catch (\Exception $e) { + $error = $e; + } + } + + if (!empty($error) || empty($data)) { + $log = sprintf( + "Error getting an access token. Error message: %s %s", + $error->getMessage(), + $error + ); + $this->log($log); + + $this->Flash->error($message); + + return $this->redirect(['action' => 'profile']); + } + + try { + $data = $this->_mapSocialUser($alias, $data); + + $user = $this->getUsersTable()->get($this->Auth->user('id')); + + $this->getUsersTable()->linkSocialAccount($user, $data); + + if ($user->getErrors()) { + $this->Flash->error($message); + } else { + $this->Flash->success(__d('CakeDC/Users', 'Social account was associated.')); + } + } catch (\Exception $e) { + $log = sprintf( + "Error retrieving the authorized user's profile data. Error message: %s %s", + $e->getMessage(), + $e + ); + $this->log($log); + + $this->Flash->error($message); + } + + return $this->redirect(['action' => 'profile']); + } + + /** + * Get the provider name based on the request or on the provider set. + * + * @param string $alias of the provider. + * @param array $data User data. + * + * @throws MissingProviderException + * @return array + */ + protected function _mapSocialUser($alias, $data) + { + $alias = ucfirst($alias); + $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$alias"; + $providerMapper = new $providerMapperClass($data); + $user = $providerMapper(); + $user['provider'] = $alias; + + return $user; + } + + /** + * Instantiates provider object. + * + * @param string $alias of the provider. + * + * @throws \Cake\Http\Exception\NotFoundException + * @return \League\OAuth2\Client\Provider\AbstractProvider|\League\OAuth1\Client\Server\Twitter + */ + protected function _getSocialProvider($alias) + { + $config = Configure::read('OAuth.providers.' . $alias); + if (!$config || !isset($config['options'], $config['options']['callbackLinkSocialUri'])) { + throw new NotFoundException; + } + + if (!isset($config['options']['clientId'], $config['options']['clientSecret'])) { + throw new NotFoundException; + } + + return $this->_createSocialProvider($config, ucfirst($alias)); + } + + /** + * Instantiates provider object. + * + * @param array $config for social provider. + * @param string $alias provider alias + * + * @throws \Cake\Http\Exception\NotFoundException + * @return \League\OAuth2\Client\Provider\AbstractProvider|\League\OAuth1\Client\Server\Twitter + */ + protected function _createSocialProvider($config, $alias = null) + { + if ($alias === SocialAccountsTable::PROVIDER_TWITTER) { + $server = new Twitter([ + 'identifier' => Configure::read('OAuth.providers.twitter.options.clientId'), + 'secret' => Configure::read('OAuth.providers.twitter.options.clientSecret'), + 'callback_uri' => Configure::read('OAuth.providers.twitter.options.callbackLinkSocialUri'), + ]); + + return $server; + } + $class = $config['className']; + $redirectUri = $config['options']['callbackLinkSocialUri']; + + unset($config['options']['callbackLinkSocialUri'], $config['options']['linkSocialUri']); + + $config['options']['redirectUri'] = $redirectUri; + + return new $class($config['options'], []); + } + + /** + * Validates OAuth2 request. + * + * @return bool + */ + protected function _validateCallbackSocialLink() + { + $queryParams = $this->request->getQueryParams(); + + if (isset($queryParams['error']) && !empty($queryParams['error'])) { + $this->log('Got error in _validateCallbackSocialLink: ' . htmlspecialchars($queryParams['error'], ENT_QUOTES, 'UTF-8')); + + return false; + } + + if (!array_key_exists('code', $queryParams)) { + return false; + } + + $sessionKey = 'SocialLink.oauth2state'; + $oauth2state = $this->request->session()->read($sessionKey); + $this->request->session()->delete($sessionKey); + $state = $queryParams['state']; + + return $oauth2state === $state; + } +} diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php new file mode 100644 index 000000000..ddd07b9c8 --- /dev/null +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -0,0 +1,180 @@ +getUsersTable()->newEntity(); + $id = $this->Auth->user('id'); + if (!empty($id)) { + $user->id = $this->Auth->user('id'); + $validatePassword = true; + //@todo add to the documentation: list of routes used + $redirect = Configure::read('Users.Profile.route'); + } else { + $user->id = $this->request->getSession()->read(Configure::read('Users.Key.Session.resetPasswordUserId')); + $validatePassword = false; + if (!$user->id) { + $this->Flash->error(__d('CakeDC/Users', 'User was not found')); + $this->redirect($this->Auth->getConfig('loginAction')); + + return; + } + //@todo add to the documentation: list of routes used + $redirect = $this->Auth->getConfig('loginAction'); + } + $this->set('validatePassword', $validatePassword); + if ($this->request->is('post')) { + try { + $validator = $this->getUsersTable()->validationPasswordConfirm(new Validator()); + if (!empty($id)) { + $validator = $this->getUsersTable()->validationCurrentPassword($validator); + } + $user = $this->getUsersTable()->patchEntity( + $user, + $this->request->getData(), + ['validate' => $validator] + ); + if ($user->getErrors()) { + $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); + } else { + $result = $this->getUsersTable()->changePassword($user); + if ($result) { + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_CHANGE_PASSWORD, ['user' => $result]); + if (!empty($event) && is_array($event->result)) { + return $this->redirect($event->result); + } + $this->Flash->success(__d('CakeDC/Users', 'Password has been changed successfully')); + + return $this->redirect($redirect); + } else { + $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); + } + } + } catch (UserNotFoundException $exception) { + $this->Flash->error(__d('CakeDC/Users', 'User was not found')); + } catch (WrongPasswordException $wpe) { + $this->Flash->error($wpe->getMessage()); + } catch (Exception $exception) { + $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); + $this->log($exception->getMessage()); + } + } + $this->set(compact('user')); + $this->set('_serialize', ['user']); + } + + /** + * Reset password + * + * @param null $token token data. + * @return void + */ + public function resetPassword($token = null) + { + $this->validate('password', $token); + } + + /** + * Reset password + * + * @return void|\Cake\Http\Response + */ + public function requestResetPassword() + { + $this->set('user', $this->getUsersTable()->newEntity()); + $this->set('_serialize', ['user']); + if (!$this->request->is('post')) { + return; + } + + $reference = $this->request->getData('reference'); + try { + $resetUser = $this->getUsersTable()->resetToken($reference, [ + 'expiration' => Configure::read('Users.Token.expiration'), + 'checkActive' => false, + 'sendEmail' => true, + 'ensureActive' => Configure::read('Users.Registration.ensureActive'), + 'type' => 'password' + ]); + if ($resetUser) { + $msg = __d('CakeDC/Users', 'Please check your email to continue with password reset process'); + $this->Flash->success($msg); + } else { + $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); + $this->Flash->error($msg); + } + + return $this->redirect(['action' => 'login']); + } catch (UserNotFoundException $exception) { + $this->Flash->error(__d('CakeDC/Users', 'User {0} was not found', $reference)); + } catch (UserNotActiveException $exception) { + $this->Flash->error(__d('CakeDC/Users', 'The user is not active')); + } catch (Exception $exception) { + $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); + $this->log($exception->getMessage()); + } + } + + /** + * resetGoogleAuthenticator + * + * Resets Google Authenticator token by setting secret_verified + * to false. + * + * @param mixed $id of the user record. + * @return mixed. + */ + public function resetGoogleAuthenticator($id = null) + { + if ($this->request->is('post')) { + try { + $query = $this->getUsersTable()->query(); + $query->update() + ->set(['secret_verified' => false, 'secret' => null]) + ->where(['id' => $id]); + $query->execute(); + + $message = __d('CakeDC/Users', 'Google Authenticator token was successfully reset'); + $this->Flash->success($message, 'default'); + } catch (\Exception $e) { + $message = $e->getMessage(); + $this->Flash->error($message, 'default'); + } + } + + return $this->redirect($this->request->referer()); + } +} diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php new file mode 100644 index 000000000..db61724d3 --- /dev/null +++ b/src/Controller/Traits/ProfileTrait.php @@ -0,0 +1,61 @@ +Auth->user('id'); + $isCurrentUser = false; + if (!Configure::read('Users.Profile.viewOthers') || empty($id)) { + $id = $loggedUserId; + } + try { + $appContain = (array)Configure::read('Auth.authenticate.' . AuthComponent::ALL . '.contain'); + $socialContain = Configure::read('Users.Social.login') ? ['SocialAccounts']: []; + $user = $this->getUsersTable()->get($id, [ + 'contain' => array_merge((array)$appContain, (array)$socialContain) + ]); + $this->set('avatarPlaceholder', Configure::read('Users.Avatar.placeholder')); + if ($user->id === $loggedUserId) { + $isCurrentUser = true; + } + } catch (RecordNotFoundException $ex) { + $this->Flash->error(__d('CakeDC/Users', 'User was not found')); + + return $this->redirect($this->request->referer()); + } catch (InvalidPrimaryKeyException $ex) { + $this->Flash->error(__d('CakeDC/Users', 'Not authorized, please login first')); + + return $this->redirect($this->request->referer()); + } + $this->set(compact('user', 'isCurrentUser')); + $this->set('_serialize', ['user', 'isCurrentUser']); + } +} diff --git a/src/Controller/Traits/ReCaptchaTrait.php b/src/Controller/Traits/ReCaptchaTrait.php new file mode 100644 index 000000000..d35773e77 --- /dev/null +++ b/src/Controller/Traits/ReCaptchaTrait.php @@ -0,0 +1,57 @@ +_getReCaptchaInstance(); + if (!empty($recaptcha)) { + $response = $recaptcha->verify($recaptchaResponse, $clientIp); + + return $response->isSuccess(); + } + + return false; + } + + /** + * Create reCaptcha instance if enabled in configuration + * + * @return \ReCaptcha\ReCaptcha + */ + protected function _getReCaptchaInstance() + { + $reCaptchaSecret = Configure::read('Users.reCaptcha.secret'); + if (!empty($reCaptchaSecret)) { + return new \ReCaptcha\ReCaptcha($reCaptchaSecret); + } + + return null; + } +} diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php new file mode 100644 index 000000000..fc29ef602 --- /dev/null +++ b/src/Controller/Traits/RegisterTrait.php @@ -0,0 +1,155 @@ +Auth->user('id'); + if (!empty($userId) && !Configure::read('Users.Registration.allowLoggedIn')) { + $this->Flash->error(__d('CakeDC/Users', 'You must log out to register a new user account')); + + return $this->redirect(Configure::read('Users.Profile.route')); + } + + $usersTable = $this->getUsersTable(); + $user = $usersTable->newEntity(); + $validateEmail = (bool)Configure::read('Users.Email.validate'); + $useTos = (bool)Configure::read('Users.Tos.required'); + $tokenExpiration = Configure::read('Users.Token.expiration'); + $options = [ + 'token_expiration' => $tokenExpiration, + 'validate_email' => $validateEmail, + 'use_tos' => $useTos + ]; + $requestData = $this->request->getData(); + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_REGISTER, [ + 'usersTable' => $usersTable, + 'options' => $options, + 'userEntity' => $user, + ]); + + if ($event->result instanceof EntityInterface) { + $data = $event->result->toArray(); + $data['password'] = $requestData['password']; //since password is a hidden property + if ($userSaved = $usersTable->register($user, $data, $options)) { + return $this->_afterRegister($userSaved); + } else { + $this->set(compact('user')); + $this->Flash->error(__d('CakeDC/Users', 'The user could not be saved')); + + return; + } + } + if ($event->isStopped()) { + return $this->redirect($event->result); + } + + $this->set(compact('user')); + $this->set('_serialize', ['user']); + + if (!$this->request->is('post')) { + return; + } + + if (!$this->_validateRegisterPost()) { + $this->Flash->error(__d('CakeDC/Users', 'Invalid reCaptcha')); + + return; + } + + $userSaved = $usersTable->register($user, $requestData, $options); + if (!$userSaved) { + $this->Flash->error(__d('CakeDC/Users', 'The user could not be saved')); + + return; + } + + return $this->_afterRegister($userSaved); + } + + /** + * Check the POST and validate it for registration, for now we check the reCaptcha + * + * @return bool + */ + protected function _validateRegisterPost() + { + if (!Configure::read('Users.reCaptcha.registration')) { + return true; + } + + return $this->validateReCaptcha( + $this->request->getData('g-recaptcha-response'), + $this->request->clientIp() + ); + } + + /** + * Prepare flash messages after registration, and dispatch afterRegister event + * + * @param EntityInterface $userSaved User entity saved + * @return Response + */ + protected function _afterRegister(EntityInterface $userSaved) + { + $validateEmail = (bool)Configure::read('Users.Email.validate'); + $message = __d('CakeDC/Users', 'You have registered successfully, please log in'); + if ($validateEmail) { + $message = __d('CakeDC/Users', 'Please validate your account before log in'); + } + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_REGISTER, [ + 'user' => $userSaved + ]); + if ($event->result instanceof Response) { + return $event->result; + } + $this->Flash->success($message); + + return $this->redirect(['action' => 'login']); + } + + /** + * Validate an email + * + * @param string $token token + * @return void + */ + public function validateEmail($token = null) + { + $this->validate('email', $token); + } +} diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php new file mode 100644 index 000000000..4f2480a0a --- /dev/null +++ b/src/Controller/Traits/SimpleCrudTrait.php @@ -0,0 +1,138 @@ +loadModel(); + $tableAlias = $table->getAlias(); + $this->set($tableAlias, $this->paginate($table)); + $this->set('tableAlias', $tableAlias); + $this->set('_serialize', [$tableAlias, 'tableAlias']); + } + + /** + * View method + * + * @param string|null $id User id. + * @return void + * @throws NotFoundException When record not found. + */ + public function view($id = null) + { + $table = $this->loadModel(); + $tableAlias = $table->getAlias(); + $entity = $table->get($id, [ + 'contain' => [] + ]); + $this->set($tableAlias, $entity); + $this->set('tableAlias', $tableAlias); + $this->set('_serialize', [$tableAlias, 'tableAlias']); + } + + /** + * Add method + * + * @return mixed Redirects on successful add, renders view otherwise. + */ + public function add() + { + $table = $this->loadModel(); + $tableAlias = $table->getAlias(); + $entity = $table->newEntity(); + $this->set($tableAlias, $entity); + $this->set('tableAlias', $tableAlias); + $this->set('_serialize', [$tableAlias, 'tableAlias']); + if (!$this->request->is('post')) { + return; + } + $entity = $table->patchEntity($entity, $this->request->getData()); + $singular = Inflector::singularize(Inflector::humanize($tableAlias)); + if ($table->save($entity)) { + $this->Flash->success(__d('CakeDC/Users', 'The {0} has been saved', $singular)); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__d('CakeDC/Users', 'The {0} could not be saved', $singular)); + } + + /** + * Edit method + * + * @param string|null $id User id. + * @return mixed Redirects on successful edit, renders view otherwise. + * @throws NotFoundException When record not found. + */ + public function edit($id = null) + { + $table = $this->loadModel(); + $tableAlias = $table->getAlias(); + $entity = $table->get($id, [ + 'contain' => [] + ]); + $this->set($tableAlias, $entity); + $this->set('tableAlias', $tableAlias); + $this->set('_serialize', [$tableAlias, 'tableAlias']); + if (!$this->request->is(['patch', 'post', 'put'])) { + return; + } + $entity = $table->patchEntity($entity, $this->request->getData()); + $singular = Inflector::singularize(Inflector::humanize($tableAlias)); + if ($table->save($entity)) { + $this->Flash->success(__d('CakeDC/Users', 'The {0} has been saved', $singular)); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__d('CakeDC/Users', 'The {0} could not be saved', $singular)); + } + + /** + * Delete method + * + * @param string|null $id User id. + * @return Response Redirects to index. + * @throws NotFoundException When record not found. + */ + public function delete($id = null) + { + $this->request->allowMethod(['post', 'delete']); + $table = $this->loadModel(); + $tableAlias = $table->getAlias(); + $entity = $table->get($id, [ + 'contain' => [] + ]); + $singular = Inflector::singularize(Inflector::humanize($tableAlias)); + if ($table->delete($entity)) { + $this->Flash->success(__d('CakeDC/Users', 'The {0} has been deleted', $singular)); + } else { + $this->Flash->error(__d('CakeDC/Users', 'The {0} could not be deleted', $singular)); + } + + return $this->redirect(['action' => 'index']); + } +} diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php new file mode 100644 index 000000000..f019f9e1d --- /dev/null +++ b/src/Controller/Traits/SocialTrait.php @@ -0,0 +1,49 @@ +request->getSession()->check(Configure::read('Users.Key.Session.social'))) { + throw new NotFoundException(); + } + $this->request->getSession()->delete('Flash.auth'); + + if ($this->request->is('post')) { + $validPost = $this->_validateRegisterPost(); + if (!$validPost) { + $this->Flash->error(__d('CakeDC/Users', 'The reCaptcha could not be validated')); + + return; + } + $user = $this->Auth->identify(); + + return $this->_afterIdentifyUser($user, true); + } + } +} diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php new file mode 100644 index 000000000..1b920f23f --- /dev/null +++ b/src/Controller/Traits/UserValidationTrait.php @@ -0,0 +1,123 @@ +getUsersTable()->validate($token, 'activateUser'); + if ($result) { + $this->Flash->success(__d('CakeDC/Users', 'User account validated successfully')); + } else { + $this->Flash->error(__d('CakeDC/Users', 'User account could not be validated')); + } + } catch (UserAlreadyActiveException $exception) { + $this->Flash->error(__d('CakeDC/Users', 'User already active')); + } + break; + case 'password': + $result = $this->getUsersTable()->validate($token); + if (!empty($result)) { + $this->Flash->success(__d('CakeDC/Users', 'Reset password token was validated successfully')); + $this->request->getSession()->write( + Configure::read('Users.Key.Session.resetPasswordUserId'), + $result->id + ); + + return $this->redirect(['action' => 'changePassword']); + } else { + $this->Flash->error(__d('CakeDC/Users', 'Reset password token could not be validated')); + } + break; + default: + $this->Flash->error(__d('CakeDC/Users', 'Invalid validation type')); + } + } catch (UserNotFoundException $ex) { + $this->Flash->error(__d('CakeDC/Users', 'Invalid token or user account already validated')); + } catch (TokenExpiredException $ex) { + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_ON_EXPIRED_TOKEN, ['type' => $type]); + if (!empty($event) && is_array($event->result)) { + return $this->redirect($event->result); + } + $this->Flash->error(__d('CakeDC/Users', 'Token already expired')); + } + + return $this->redirect(['action' => 'login']); + } + + /** + * Resend Token validation + * + * @return mixed + */ + public function resendTokenValidation() + { + $this->set('user', $this->getUsersTable()->newEntity()); + $this->set('_serialize', ['user']); + if (!$this->request->is('post')) { + return; + } + $reference = $this->request->getData('reference'); + try { + if ($this->getUsersTable()->resetToken($reference, [ + 'expiration' => Configure::read('Users.Token.expiration'), + 'checkActive' => true, + 'sendEmail' => true, + 'type' => 'email' + ])) { + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_RESEND_TOKEN_VALIDATION); + if (!empty($event) && is_array($event->result)) { + return $this->redirect($event->result); + } + $this->Flash->success(__d( + 'CakeDC/Users', + 'Token has been reset successfully. Please check your email.' + )); + } else { + $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); + } + + return $this->redirect(['action' => 'login']); + } catch (UserNotFoundException $ex) { + $this->Flash->error(__d('CakeDC/Users', 'User {0} was not found', $reference)); + } catch (UserAlreadyActiveException $ex) { + $this->Flash->error(__d('CakeDC/Users', 'User {0} is already active', $reference)); + } catch (Exception $ex) { + $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); + } + } +} diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php new file mode 100644 index 000000000..b86bd0940 --- /dev/null +++ b/src/Controller/UsersController.php @@ -0,0 +1,41 @@ + +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2017-10-14 23:45+0000\n" +"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" +"Last-Translator: NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#: Auth/SocialAuthenticate.php:456 +msgid "Provider cannot be empty" +msgstr "" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "" + +#: Controller/Component/RememberMeComponent.php:68 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" + +#: Controller/Component/UsersAuthComponent.php:204 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" + +#: Controller/Traits/LinkSocialTrait.php:54 +msgid "Could not associate account, please try again." +msgstr "" + +#: Controller/Traits/LinkSocialTrait.php:77 +msgid "Social account was associated." +msgstr "" + +#: Controller/Traits/LoginTrait.php:104 +msgid "Issues trying to log in with your social account" +msgstr "" + +#: Controller/Traits/LoginTrait.php:109 +#: Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "" + +#: Controller/Traits/LoginTrait.php:120 +msgid "Your user has not been validated yet. Please check your inbox for instructions" +msgstr "" + +#: Controller/Traits/LoginTrait.php:125 +msgid "Your social account has not been validated yet. Please check your inbox for instructions" +msgstr "" + +#: Controller/Traits/LoginTrait.php:180 +#: Controller/Traits/RegisterTrait.php:82 +msgid "Invalid reCaptcha" +msgstr "" + +#: Controller/Traits/LoginTrait.php:191 +msgid "You are already logged in" +msgstr "" + +#: Controller/Traits/LoginTrait.php:212 +msgid "Please enable Google Authenticator first." +msgstr "" + +#: Controller/Traits/LoginTrait.php:287 +msgid "Verification code is invalid. Try again" +msgstr "" + +#: Controller/Traits/LoginTrait.php:340 +msgid "Username or password is incorrect" +msgstr "" + +#: Controller/Traits/LoginTrait.php:363 +msgid "You've successfully logged out" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:49;82 +#: Controller/Traits/ProfileTrait.php:50 +msgid "User was not found" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:70;78;86 +msgid "Password could not be changed" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:74 +msgid "Password has been changed successfully" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:84 +msgid "{0}" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:127 +msgid "Please check your email to continue with password reset process" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:130 +#: Shell/UsersShell.php:247 +msgid "The password token could not be generated. Please try again" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:136 +#: Controller/Traits/UserValidationTrait.php:107 +msgid "User {0} was not found" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:138 +msgid "The user is not active" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:140 +#: Controller/Traits/UserValidationTrait.php:102;111 +msgid "Token could not be reset" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:164 +msgid "Google Authenticator token was successfully reset" +msgstr "" + +#: Controller/Traits/ProfileTrait.php:54 +msgid "Not authorized, please login first" +msgstr "" + +#: Controller/Traits/RegisterTrait.php:43 +msgid "You must log out to register a new user account" +msgstr "" + +#: Controller/Traits/RegisterTrait.php:89 +msgid "The user could not be saved" +msgstr "" + +#: Controller/Traits/RegisterTrait.php:123 +msgid "You have registered successfully, please log in" +msgstr "" + +#: Controller/Traits/RegisterTrait.php:125 +msgid "Please validate your account before log in" +msgstr "" + +#: Controller/Traits/SimpleCrudTrait.php:77;107 +msgid "The {0} has been saved" +msgstr "" + +#: Controller/Traits/SimpleCrudTrait.php:81;111 +msgid "The {0} could not be saved" +msgstr "" + +#: Controller/Traits/SimpleCrudTrait.php:131 +msgid "The {0} has been deleted" +msgstr "" + +#: Controller/Traits/SimpleCrudTrait.php:133 +msgid "The {0} could not be deleted" +msgstr "" + +#: Controller/Traits/SocialTrait.php:40 +msgid "The reCaptcha could not be validated" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:43 +msgid "User account validated successfully" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:45 +msgid "User account could not be validated" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:48 +msgid "User already active" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:54 +msgid "Reset password token was validated successfully" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Reset password token could not be validated" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:66 +msgid "Invalid validation type" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:69 +msgid "Invalid token or user account already validated" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:71 +msgid "Token already expired" +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:97 +msgid "Token has been reset successfully. Please check your email." +msgstr "" + +#: Controller/Traits/UserValidationTrait.php:109 +msgid "User {0} is already active" +msgstr "" + +#: Mailer/UsersMailer.php:34 +msgid "Your account validation link" +msgstr "" + +#: Mailer/UsersMailer.php:52 +msgid "{0}Your reset password link" +msgstr "" + +#: Mailer/UsersMailer.php:75 +msgid "{0}Your social account validation link" +msgstr "" + +#: Model/Behavior/AuthFinderBehavior.php:49 +msgid "Missing 'username' in options data" +msgstr "" + +#: Model/Behavior/LinkSocialBehavior.php:53 +msgid "Social account already associated to another user" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:45 +msgid "Reference cannot be null" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:50 +msgid "Token expiration cannot be empty" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:56;117 +msgid "User not found" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112;205 +msgid "User account already validated" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:67 +msgid "User not active" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:122 +msgid "The current password does not match" +msgstr "" + +#: Model/Behavior/PasswordBehavior.php:125 +msgid "You cannot use the current password as the new one" +msgstr "" + +#: Model/Behavior/RegisterBehavior.php:90 +msgid "User not found for the given token and email." +msgstr "" + +#: Model/Behavior/RegisterBehavior.php:93 +msgid "Token has already expired user with no token" +msgstr "" + +#: Model/Behavior/SocialAccountBehavior.php:103;130 +msgid "Account already validated" +msgstr "" + +#: Model/Behavior/SocialAccountBehavior.php:106;133 +msgid "Account not found for the given token and email." +msgstr "" + +#: Model/Behavior/SocialBehavior.php:82 +msgid "Unable to login user with reference {0}" +msgstr "" + +#: Model/Behavior/SocialBehavior.php:121 +msgid "Email not present" +msgstr "" + +#: Model/Table/UsersTable.php:81 +msgid "Your password does not match your confirm password. Please try again" +msgstr "" + +#: Model/Table/UsersTable.php:173 +msgid "Username already exists" +msgstr "" + +#: Model/Table/UsersTable.php:179 +msgid "Email already exists" +msgstr "" + +#: Shell/UsersShell.php:58 +msgid "Utilities for CakeDC Users Plugin" +msgstr "" + +#: Shell/UsersShell.php:60 +msgid "Activate an specific user" +msgstr "" + +#: Shell/UsersShell.php:63 +msgid "Add a new superadmin user for testing purposes" +msgstr "" + +#: Shell/UsersShell.php:66 +msgid "Add a new user" +msgstr "" + +#: Shell/UsersShell.php:69 +msgid "Change the role for an specific user" +msgstr "" + +#: Shell/UsersShell.php:72 +msgid "Deactivate an specific user" +msgstr "" + +#: Shell/UsersShell.php:75 +msgid "Delete an specific user" +msgstr "" + +#: Shell/UsersShell.php:78 +msgid "Reset the password via email" +msgstr "" + +#: Shell/UsersShell.php:81 +msgid "Reset the password for all users" +msgstr "" + +#: Shell/UsersShell.php:84 +msgid "Reset the password for an specific user" +msgstr "" + +#: Shell/UsersShell.php:133;159 +msgid "Please enter a password." +msgstr "" + +#: Shell/UsersShell.php:137 +msgid "Password changed for all users" +msgstr "" + +#: Shell/UsersShell.php:138;166 +msgid "New password: {0}" +msgstr "" + +#: Shell/UsersShell.php:156;184;262;359 +msgid "Please enter a username." +msgstr "" + +#: Shell/UsersShell.php:165 +msgid "Password changed for user: {0}" +msgstr "" + +#: Shell/UsersShell.php:187 +msgid "Please enter a role." +msgstr "" + +#: Shell/UsersShell.php:193 +msgid "Role changed for user: {0}" +msgstr "" + +#: Shell/UsersShell.php:194 +msgid "New role: {0}" +msgstr "" + +#: Shell/UsersShell.php:209 +msgid "User was activated: {0}" +msgstr "" + +#: Shell/UsersShell.php:224 +msgid "User was de-activated: {0}" +msgstr "" + +#: Shell/UsersShell.php:236 +msgid "Please enter a username or email." +msgstr "" + +#: Shell/UsersShell.php:244 +msgid "Please ask the user to check the email to continue with password reset process" +msgstr "" + +#: Shell/UsersShell.php:308 +msgid "Superuser added:" +msgstr "" + +#: Shell/UsersShell.php:310 +msgid "User added:" +msgstr "" + +#: Shell/UsersShell.php:312 +msgid "Id: {0}" +msgstr "" + +#: Shell/UsersShell.php:313 +msgid "Username: {0}" +msgstr "" + +#: Shell/UsersShell.php:314 +msgid "Email: {0}" +msgstr "" + +#: Shell/UsersShell.php:315 +msgid "Role: {0}" +msgstr "" + +#: Shell/UsersShell.php:316 +msgid "Password: {0}" +msgstr "" + +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" +msgstr "" + +#: Shell/UsersShell.php:337 +msgid "The user was not found." +msgstr "" + +#: Shell/UsersShell.php:367 +msgid "The user {0} was not deleted. Please try again" +msgstr "" + +#: Shell/UsersShell.php:369 +msgid "The user {0} was deleted successfully" +msgstr "" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "If the link is not correctly displayed, please copy the following address in your web browser {0}" +msgstr "" + +#: Template/Email/html/reset_password.ctp:34 +#: Template/Email/html/social_account_validation.ctp:39 +#: Template/Email/html/validation.ctp:34 +#: Template/Email/text/reset_password.ctp:28 +#: Template/Email/text/social_account_validation.ctp:30 +#: Template/Email/text/validation.ctp:28 +msgid "Thank you" +msgstr "" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "Please copy the following address in your web browser to activate your social login {0}" +msgstr "" + +#: Template/Users/add.ctp:13 +#: Template/Users/edit.ctp:16 +#: Template/Users/index.ctp:13;26 +#: Template/Users/view.ctp:15 +msgid "Actions" +msgstr "" + +#: Template/Users/add.ctp:15 +#: Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:23 +msgid "List Users" +msgstr "" + +#: Template/Users/add.ctp:21 +#: Template/Users/register.ctp:17 +msgid "Add User" +msgstr "" + +#: Template/Users/add.ctp:23 +#: Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 +#: Template/Users/profile.ctp:30 +#: Template/Users/register.ctp:19 +#: Template/Users/view.ctp:33 +msgid "Username" +msgstr "" + +#: Template/Users/add.ctp:24 +#: Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 +#: Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:20 +#: Template/Users/view.ctp:35 +msgid "Email" +msgstr "" + +#: Template/Users/add.ctp:25 +#: Template/Users/register.ctp:21 +msgid "Password" +msgstr "" + +#: Template/Users/add.ctp:26 +#: Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 +#: Template/Users/register.ctp:26 +msgid "First name" +msgstr "" + +#: Template/Users/add.ctp:27 +#: Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 +#: Template/Users/register.ctp:27 +msgid "Last name" +msgstr "" + +#: Template/Users/add.ctp:30 +#: Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:49;74 +msgid "Active" +msgstr "" + +#: Template/Users/add.ctp:34 +#: Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 +#: Template/Users/register.ctp:36 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "" + +#: Template/Users/change_password.ctp:21 +#: Template/Users/register.ctp:24 +msgid "Confirm password" +msgstr "" + +#: Template/Users/edit.ctp:21 +#: Template/Users/index.ctp:40 +msgid "Delete" +msgstr "" + +#: Template/Users/edit.ctp:23 +#: Template/Users/index.ctp:40 +#: Template/Users/view.ctp:21 +msgid "Are you sure you want to delete # {0}?" +msgstr "" + +#: Template/Users/edit.ctp:33 +#: Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "" + +#: Template/Users/edit.ctp:39 +#: Template/Users/view.ctp:43 +msgid "Token" +msgstr "" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "" + +#: Template/Users/edit.ctp:63 +msgid "Reset Google Authenticator Token" +msgstr "" + +#: Template/Users/edit.ctp:69 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "" + +#: Template/Users/index.ctp:37 +msgid "View" +msgstr "" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "" + +#: Template/Users/index.ctp:39 +msgid "Edit" +msgstr "" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "" + +#: Template/Users/profile.ctp:21 +#: View/Helper/UserHelper.php:54 +msgid "{0} {1}" +msgstr "" + +#: Template/Users/profile.ctp:27 +msgid "Change Password" +msgstr "" + +#: Template/Users/profile.ctp:38 +#: Template/Users/view.ctp:68 +msgid "Social Accounts" +msgstr "" + +#: Template/Users/profile.ctp:42 +#: Template/Users/view.ctp:73 +msgid "Avatar" +msgstr "" + +#: Template/Users/profile.ctp:43 +#: Template/Users/view.ctp:72 +msgid "Provider" +msgstr "" + +#: Template/Users/profile.ctp:44 +msgid "Link" +msgstr "" + +#: Template/Users/profile.ctp:51 +msgid "Link to {0}" +msgstr "" + +#: Template/Users/register.ctp:29 +msgid "Accept TOS conditions?" +msgstr "" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "" + +#: Template/Users/verify.ctp:13 +msgid "Verification Code" +msgstr "" + +#: Template/Users/verify.ctp:15 +msgid " Verify" +msgstr "" + +#: Template/Users/view.ctp:19 +msgid "Delete User" +msgstr "" + +#: Template/Users/view.ctp:24 +msgid "New User" +msgstr "" + +#: Template/Users/view.ctp:31 +msgid "Id" +msgstr "" + +#: Template/Users/view.ctp:37 +msgid "First Name" +msgstr "" + +#: Template/Users/view.ctp:39 +msgid "Last Name" +msgstr "" + +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "" + +#: Template/Users/view.ctp:45 +msgid "Api Token" +msgstr "" + +#: Template/Users/view.ctp:53 +msgid "Token Expires" +msgstr "" + +#: Template/Users/view.ctp:55 +msgid "Activation Date" +msgstr "" + +#: Template/Users/view.ctp:57 +msgid "Tos Date" +msgstr "" + +#: Template/Users/view.ctp:59;75 +msgid "Created" +msgstr "" + +#: Template/Users/view.ctp:61;76 +msgid "Modified" +msgstr "" + +#: View/Helper/UserHelper.php:45 +msgid "Sign in with" +msgstr "" + +#: View/Helper/UserHelper.php:48 +msgid "fa fa-{0}" +msgstr "" + +#: View/Helper/UserHelper.php:57 +msgid "btn btn-social btn-{0} " +msgstr "" + +#: View/Helper/UserHelper.php:106 +msgid "Logout" +msgstr "" + +#: View/Helper/UserHelper.php:123 +msgid "Welcome, {0}" +msgstr "" + +#: View/Helper/UserHelper.php:146 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" + +#: View/Helper/UserHelper.php:205 +msgid "btn btn-social btn-{0}" +msgstr "" + +#: View/Helper/UserHelper.php:211 +msgid "Connected with {0}" +msgstr "" + +#: View/Helper/UserHelper.php:216 +msgid "Connect with {0}" +msgstr "" + diff --git a/src/Locale/ar_OM/Users.mo b/src/Locale/ar_OM/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..8223903a8986118dcad05c4c848764badca7af6b GIT binary patch literal 18521 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 +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2017-10-14 23:45+0000\n" +"PO-Revision-Date: 2018-11-13 12:43+0400\n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n" +"X-Generator: Poedit 2.2\n" +"Last-Translator: \n" +"Language: ar\n" + +#: Auth/SocialAuthenticate.php:456 +msgid "Provider cannot be empty" +msgstr "Ł„Ų§ ŁŠŁ…ŁƒŁ† ŲŖŲ±Łƒ Ł…Ų²ŁˆŲÆ Ų§Ł„Ų®ŲÆŁ…Ų© ŁŲ§Ų±Ųŗ" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "ŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų­Ų³Ų§ŲØ ŲØŁ†Ų¬Ų§Ų­" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "ŲŖŲ¹Ų°Ų± Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų­Ų³Ų§ŲØ" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Ų±Ł…Ų² Token ŲŗŁŠŲ± ŲµŲ§Ł„Ų­ Łˆ/ Ų£Łˆ Ų§Ł„Ų­Ų³Ų§ŲØ ŲŗŁŠŲ± ŲµŲ­ŁŠŲ­" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "ŲŖŁ… ŲŖŁ†Ų“ŁŠŲ· Ų§Ł„Ų­Ų³Ų§ŲØ Ł…Ų³ŲØŁ‚Ų§Ł‹" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "ŲŖŲ¹Ų°Ų± Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų­Ų³Ų§ŲØ " + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "ŲŖŁ… Ų„Ų±Ų³Ų§Ł„ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ ŲØŁ†Ų¬Ų§Ų­ " + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "ŲŖŲ¹Ų°Ų± Ų„Ų±Ų³Ų§Ł„ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "Ų­Ų³Ų§ŲØ ŲŗŁŠŲ± ŲµŲ§Ł„Ų­" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "Ł„Ų§ ŁŠŁ…ŁƒŁ† Ų§Ų±Ų³Ų§Ł„ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ " + +#: Controller/Component/RememberMeComponent.php:68 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "ŁŠŲ¬ŲØ Ų§Ł† ŁŠŁƒŁˆŁ† Ų§Ł„Ł…ŁŲŖŲ§Ų­ ŲØŲ·ŁˆŁ„ 32 ŲØŲ§ŁŠŲŖ" + +#: Controller/Component/UsersAuthComponent.php:204 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"Ł„Ų§ ŁŠŁ…ŁƒŁ† ŲŖŁŲ¹ŁŠŁ„ Ų§Ł„ŲŖŲ­Ł‚Ł‚ ŲØŲ§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ų§Ų°Ų§ ŁƒŲ§Ł† Ų§Ų³ŲŖŲ®ŲÆŲ§Ł… Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§ŁƒŲŖŲ±ŁˆŁ†ŁŠ ŲŗŁŠŲ± " +"Ł…ŁŲ¹Ł„ " + +#: Controller/Traits/LinkSocialTrait.php:54 +msgid "Could not associate account, please try again." +msgstr "ŲŖŲ¹Ų°Ų± Ų±ŲØŲ· Ų§Ł„Ų­Ų³Ų§ŲØ ŲŒ Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„Ł…Ų­Ų§ŁˆŁ„Ų© Ł…Ų±Ł‡ Ų£Ų®Ų±Ł‰." + +#: Controller/Traits/LinkSocialTrait.php:77 +msgid "Social account was associated." +msgstr "ŲŖŁ… Ų±ŲØŲ· Ų§Ł„Ų­Ų³Ų§ŲØ Ł…Ų³ŲØŁ‚Ų§Ł‹" + +#: Controller/Traits/LoginTrait.php:104 +msgid "Issues trying to log in with your social account" +msgstr "ŲŖŲ¹Ų°Ų± ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„ ŲØŲ§Ų³ŲŖŲ®ŲÆŲ§Ł… Ų­Ų³Ų§ŲØŁƒ" + +#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ ŲØŲ±ŁŠŲÆŁƒ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ" + +#: Controller/Traits/LoginTrait.php:120 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Ł„Ł… ŁŠŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ų§Ł„Ų®Ų§Ųµ ŲØŁƒ ŲØŲ¹ŲÆ. Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁˆŲ§Ų±ŲÆ " +"Ł„Ł„Ų­ŲµŁˆŁ„ Ų¹Ł„ŁŠ ŲŖŲ¹Ł„ŁŠŁ…Ų§ŲŖ" + +#: Controller/Traits/LoginTrait.php:125 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Ł„Ł… ŁŠŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų­Ų³Ų§ŲØŁƒ Ų§Ł„Ų§Ų¬ŲŖŁ…Ų§Ų¹ŁŠ ŲØŲ¹ŲÆ. Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁˆŲ§Ų±ŲÆ " +"Ł„Ł„Ų­ŲµŁˆŁ„ Ų¹Ł„ŁŠ ŲŖŲ¹Ł„ŁŠŁ…Ų§ŲŖ" + +#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 +msgid "Invalid reCaptcha" +msgstr "reCaptcha ŲŗŁŠŲ± ŲµŲ§Ł„Ų­Ł‡" + +#: Controller/Traits/LoginTrait.php:191 +msgid "You are already logged in" +msgstr "ŲŖŁ… ŲŖŲ³Ų¬ŁŠŁ„ ŲÆŲ®ŁˆŁ„Łƒ Ł…Ų³ŲØŁ‚Ų§Ł‹" + +#: Controller/Traits/LoginTrait.php:212 +msgid "Please enable Google Authenticator first." +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” ŲŖŁ…ŁƒŁŠŁ† Ų£ŲÆŲ§Ł‡ Ł…ŲµŲ§ŲÆŁ‚Ł‡ Google Ų£ŁˆŁ„Ų§." + +#: Controller/Traits/LoginTrait.php:287 +msgid "Verification code is invalid. Try again" +msgstr "Ų±Ł…Ų² Ų§Ł„ŲŖŲ­Ł‚Ł‚ ŲŗŁŠŲ± ŲµŲ§Ł„Ų­. Ų­Ų§ŁˆŁ„ Ł…Ų±Ų© Ų£Ų®Ų±Ł‰" + +#: Controller/Traits/LoginTrait.php:340 +msgid "Username or password is incorrect" +msgstr "Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ų£Łˆ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± ŲŗŁŠŲ± ŲµŲ­ŁŠŲ­Ł‡" + +#: Controller/Traits/LoginTrait.php:363 +msgid "You've successfully logged out" +msgstr "Ł„Ł‚ŲÆ Ł‚Ł…ŲŖ ŲØŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„Ų®Ų±ŁˆŲ¬ ŲØŁ†Ų¬Ų§Ų­" + +#: Controller/Traits/PasswordManagementTrait.php:49;82 +#: Controller/Traits/ProfileTrait.php:50 +msgid "User was not found" +msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„ŁŠ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Controller/Traits/PasswordManagementTrait.php:70;78;86 +msgid "Password could not be changed" +msgstr "ŲŖŲ¹Ų°Ų± ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Controller/Traits/PasswordManagementTrait.php:74 +msgid "Password has been changed successfully" +msgstr "ŲŖŁ… ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± ŲØŁ†Ų¬Ų§Ų­" + +#: Controller/Traits/PasswordManagementTrait.php:84 +msgid "{0}" +msgstr "{0}" + +#: Controller/Traits/PasswordManagementTrait.php:127 +msgid "Please check your email to continue with password reset process" +msgstr "" +"ŁŠŲ±Ų¬Ł‰ Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ų§Ł„Ų®Ų§Ųµ ŲØŁƒ Ł„Ł…ŲŖŲ§ŲØŲ¹Ł‡ Ų¹Ł…Ł„ŁŠŁ‡ Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 +msgid "The password token could not be generated. Please try again" +msgstr "ŲŖŲ¹Ų°Ų± Ų„Ł†Ų“Ų§Ų” Ų§Ł„Ų±Ł…Ų² Ų§Ł„Ł…Ł…ŁŠŲ² Ł„ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±. Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„Ł…Ų­Ų§ŁˆŁ„Ų© Ł…Ų±Ł‡ Ų£Ų®Ų±Ł‰" + +#: Controller/Traits/PasswordManagementTrait.php:136 +#: Controller/Traits/UserValidationTrait.php:107 +msgid "User {0} was not found" +msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„ŁŠ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… {0}" + +#: Controller/Traits/PasswordManagementTrait.php:138 +msgid "The user is not active" +msgstr "Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… ŲŗŁŠŲ± Ł†Ų“Ų·" + +#: Controller/Traits/PasswordManagementTrait.php:140 +#: Controller/Traits/UserValidationTrait.php:102;111 +msgid "Token could not be reset" +msgstr "ŲŖŲ¹Ų°Ų± Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† Ų§Ł„Ų±Ł…Ų² Ų§Ł„Ł…Ł…ŁŠŲ²" + +#: Controller/Traits/PasswordManagementTrait.php:164 +msgid "Google Authenticator token was successfully reset" +msgstr "ŲŖŁ…ŲŖ Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† Ų±Ł…Ų² Ł…ŲµŲ§ŲÆŁ‚Ł‡ Google ŲØŁ†Ų¬Ų§Ų­" + +#: Controller/Traits/ProfileTrait.php:54 +msgid "Not authorized, please login first" +msgstr "ŲŗŁŠŲ± Ł…ŲµŲ±Ų­ ŲØŁ‡ ŲŒ Ų§Ł„Ų±Ų¬Ų§Ų” ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„ Ų£ŁˆŁ„Ų§" + +#: Controller/Traits/RegisterTrait.php:43 +msgid "You must log out to register a new user account" +msgstr "ŁŠŲ¬ŲØ ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„Ų®Ų±ŁˆŲ¬ Ł„ŲŖŲ³Ų¬ŁŠŁ„ Ų­Ų³Ų§ŲØ Ł…Ų³ŲŖŲ®ŲÆŁ… Ų¬ŲÆŁŠŲÆ" + +#: Controller/Traits/RegisterTrait.php:89 +msgid "The user could not be saved" +msgstr "ŲŖŲ¹Ų°Ų± Ų­ŁŲø Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Controller/Traits/RegisterTrait.php:123 +msgid "You have registered successfully, please log in" +msgstr "Ł„Ł‚ŲÆ Ł‚Ł…ŲŖ ŲØŲ§Ł„ŲŖŲ³Ų¬ŁŠŁ„ ŲØŁ†Ų¬Ų§Ų­ ŲŒ Ų§Ł„Ų±Ų¬Ų§Ų” ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„" + +#: Controller/Traits/RegisterTrait.php:125 +msgid "Please validate your account before log in" +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” ŲŖŁ†Ų“ŁŠŲ· Ų­Ų³Ų§ŲØŁƒ Ł‚ŲØŁ„ ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„" + +#: Controller/Traits/SimpleCrudTrait.php:77;107 +msgid "The {0} has been saved" +msgstr "ŲŖŁ… Ų­ŁŲø {0}" + +#: Controller/Traits/SimpleCrudTrait.php:81;111 +msgid "The {0} could not be saved" +msgstr "ŲŖŲ¹Ų°Ų± Ų­ŁŲø {0}" + +#: Controller/Traits/SimpleCrudTrait.php:131 +msgid "The {0} has been deleted" +msgstr "ŲŖŁ… Ų­Ų°Ł {0}" + +#: Controller/Traits/SimpleCrudTrait.php:133 +msgid "The {0} could not be deleted" +msgstr "ŲŖŲ¹Ų°Ų± Ų­Ų°Ł {0}" + +#: Controller/Traits/SocialTrait.php:40 +msgid "The reCaptcha could not be validated" +msgstr "ŲŖŲ¹Ų°Ų± Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© reCaptcha" + +#: Controller/Traits/UserValidationTrait.php:43 +msgid "User account validated successfully" +msgstr "ŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų­Ų³Ų§ŲØ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… ŲØŁ†Ų¬Ų§Ų­" + +#: Controller/Traits/UserValidationTrait.php:45 +msgid "User account could not be validated" +msgstr "ŲŖŲ¹Ų°Ų± Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų­Ų³Ų§ŲØ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Controller/Traits/UserValidationTrait.php:48 +msgid "User already active" +msgstr "Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł†Ų“Ų· ŲØŲ§Ł„ŁŲ¹Ł„" + +#: Controller/Traits/UserValidationTrait.php:54 +msgid "Reset password token was validated successfully" +msgstr "ŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų±Ł…Ų² Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± ŲØŁ†Ų¬Ų§Ų­" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Reset password token could not be validated" +msgstr "ŲŖŲ¹Ų°Ų± Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų±Ł…Ų² Ų§Ł„Ł…Ł…ŁŠŲ² Ł„Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Controller/Traits/UserValidationTrait.php:66 +msgid "Invalid validation type" +msgstr "ŁˆŲ³ŁŠŁ„Ų© Ų§Ł„ŲŖŲ­Ł‚Ł‚ ŲŗŁŠŲ± ŲµŲ§Ł„Ų­Ų©" + +#: Controller/Traits/UserValidationTrait.php:69 +msgid "Invalid token or user account already validated" +msgstr "Ų§Ł„Ų±Ł…Ų² (token) ŲŗŁŠŲ± ŲµŲ­ŁŠŲ­ Ų§Łˆ ŲŖŁ… Ų§Ų³ŲŖŲ®ŲÆŲ§Ł…Ł‡ Ł…Ł† Ł‚ŲØŁ„" + +#: Controller/Traits/UserValidationTrait.php:71 +msgid "Token already expired" +msgstr "Ų§Ł„Ų±Ł…Ų² token Ų§Ł†ŲŖŁ‡ŲŖ ŲµŁ„Ų§Ų­ŁŠŲŖŁ‡ " + +#: Controller/Traits/UserValidationTrait.php:97 +msgid "Token has been reset successfully. Please check your email." +msgstr "ŲŖŁ… Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† token ŲØŁ†Ų¬Ų§Ų­. ŁŠŲ±Ų¬Ł‰ Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲØŲ±ŁŠŲÆŁƒ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ." + +#: Controller/Traits/UserValidationTrait.php:109 +msgid "User {0} is already active" +msgstr "Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… {0} Ł†Ų“Ų· ŲØŲ§Ł„ŁŲ¹Ł„" + +#: Mailer/UsersMailer.php:34 +msgid "Your account validation link" +msgstr "Ų±Ų§ŲØŲ· Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† Ų§Ł„Ų­Ų³Ų§ŲØŁƒ" + +#: Mailer/UsersMailer.php:52 +msgid "{0}Your reset password link" +msgstr "{0} Ų±Ų§ŲØŲ· Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Mailer/UsersMailer.php:75 +msgid "{0}Your social account validation link" +msgstr "{0} Ų±Ų§ŲØŲ· Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų­Ų³Ų§ŲØ" + +#: Model/Behavior/AuthFinderBehavior.php:49 +msgid "Missing 'username' in options data" +msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„Ł‰ Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Model/Behavior/LinkSocialBehavior.php:53 +msgid "Social account already associated to another user" +msgstr "Ų§Ł„Ų­Ų³Ų§ŲØ Ł…Ų±ŲŖŲØŲ· ŲØŲ§Ł„ŁŲ¹Ł„ ŲØŁ…Ų³ŲŖŲ®ŲÆŁ… Ų¢Ų®Ų±" + +#: Model/Behavior/PasswordBehavior.php:45 +msgid "Reference cannot be null" +msgstr "Ł„Ų§ ŁŠŁ…ŁƒŁ† Ų§Ł† ŁŠŁƒŁˆŁ† Ų§Ł„Ł…Ų±Ų¬Ų¹ ŁŲ§Ų±ŲŗŲ§" + +#: Model/Behavior/PasswordBehavior.php:50 +msgid "Token expiration cannot be empty" +msgstr "Ł„Ų§ ŁŠŁ…ŁƒŁ† ŲŖŲ±Łƒ Ų­Ł‚Ł„ Ų§Ł†ŲŖŁ‡Ų§Ų” ŲµŁ„Ų§Ų­ŁŠŲ© Token ŁŲ§Ų±ŲŗŲ§Ł‹ " + +#: Model/Behavior/PasswordBehavior.php:56;117 +msgid "User not found" +msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„ŁŠ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112;205 +msgid "User account already validated" +msgstr "ŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų­Ų³Ų§ŲØ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Model/Behavior/PasswordBehavior.php:67 +msgid "User not active" +msgstr "Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… ŲŗŁŠŲ± Ł†Ų“Ų·" + +#: Model/Behavior/PasswordBehavior.php:122 +msgid "The current password does not match" +msgstr "Ł„Ų§ ŲŖŲŖŲ·Ų§ŲØŁ‚ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų§Ł„Ų­Ų§Ł„ŁŠŲ©" + +#: Model/Behavior/PasswordBehavior.php:125 +msgid "You cannot use the current password as the new one" +msgstr "Ł„Ų§ ŁŠŁ…ŁƒŁ†Łƒ Ų§Ų³ŲŖŲ®ŲÆŲ§Ł… ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų§Ł„Ų­Ų§Ł„ŁŠŲ© ŁƒŁ€ ŁƒŁ„Ł…Ų© Ų³Ų± Ų¬ŲÆŁŠŲÆŲ©" + +#: Model/Behavior/RegisterBehavior.php:90 +msgid "User not found for the given token and email." +msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„Ł‰ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł„Ł‡Ų°Ų§ Ų§Ł„Ų±Ł…Ų² Łˆ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ " + +#: Model/Behavior/RegisterBehavior.php:93 +msgid "Token has already expired user with no token" +msgstr "Ų§Ł„Ų±Ł…Ų² Token Ų§Ł†ŲŖŁ‡ŲŖ ŲµŁ„Ų§Ų­ŁŠŲŖŁ‡, Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… ŲØŲÆŁˆŁ† Token Ų§Ł„Ų¢Ł† " + +#: Model/Behavior/SocialAccountBehavior.php:103;130 +msgid "Account already validated" +msgstr "ŲŖŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† ŲµŲ­Ų© Ų§Ł„Ų­Ų³Ų§ŲØ" + +#: Model/Behavior/SocialAccountBehavior.php:106;133 +msgid "Account not found for the given token and email." +msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„Ł‰ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł„Ł‡Ų°Ų§ Ų§Ł„Ų±Ł…Ų² Łˆ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ " + +#: Model/Behavior/SocialBehavior.php:82 +msgid "Unable to login user with reference {0}" +msgstr "ŲŗŁŠŲ± Ł‚Ų§ŲÆŲ± Ų¹Ł„ŁŠ ŲŖŲ³Ų¬ŁŠŁ„ ŲÆŲ®ŁˆŁ„ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ Ų§Ł„Ł…Ų±Ų¬Ų¹ {0}" + +#: Model/Behavior/SocialBehavior.php:121 +msgid "Email not present" +msgstr "Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ ŲŗŁŠŲ± Ł…ŁˆŲ¬ŁˆŲÆ" + +#: Model/Table/UsersTable.php:81 +msgid "Your password does not match your confirm password. Please try again" +msgstr "" +"Ł„Ų§ ŲŖŲŖŲ·Ų§ŲØŁ‚ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų§Ł„Ų®Ų§ŲµŲ© ŲØŁƒ Ł…Ų¹ ŲŖŲ§ŁƒŁŠŲÆ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±. Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„Ł…Ų­Ų§ŁˆŁ„Ų© Ł…Ų±Ł‡ " +"Ų£Ų®Ų±Ł‰" + +#: Model/Table/UsersTable.php:173 +msgid "Username already exists" +msgstr "Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…ŁˆŲ¬ŁˆŲÆ ŲØŲ§Ł„ŁŲ¹Ł„" + +#: Model/Table/UsersTable.php:179 +msgid "Email already exists" +msgstr "Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ł…ŁˆŲ¬ŁˆŲÆ ŲØŲ§Ł„ŁŲ¹Ł„" + +#: Shell/UsersShell.php:58 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Ų§Ł„Ų£ŲÆŁˆŲ§ŲŖ Ų§Ł„Ł…Ų³Ų§Ų¹ŲÆŲ© Ł„Ų„Ų¶Ų§ŁŲ© CakeDC/Users " + +#: Shell/UsersShell.php:60 +msgid "Activate an specific user" +msgstr "ŲŖŁ†Ų“ŁŠŲ· Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ŁŠŁ†" + +#: Shell/UsersShell.php:63 +msgid "Add a new superadmin user for testing purposes" +msgstr "Ų£Ų¶Ų§ŁŁ‡ Ł…Ų³ŲŖŲ®ŲÆŁ… Ų¬ŲÆŁŠŲÆ super admin Ł„Ų£ŲŗŲ±Ų§Ų¶ Ų§Ł„Ų§Ų®ŲŖŲØŲ§Ų±" + +#: Shell/UsersShell.php:66 +msgid "Add a new user" +msgstr "Ų£Ų¶Ų§ŁŁ‡ Ł…Ų³ŲŖŲ®ŲÆŁ… Ų¬ŲÆŁŠŲÆ" + +#: Shell/UsersShell.php:69 +msgid "Change the role for an specific user" +msgstr "ŲŖŲŗŁŠŁŠŲ± ŲÆŁˆŲ± Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ŁŠŁ†" + +#: Shell/UsersShell.php:72 +msgid "Deactivate an specific user" +msgstr "Ų„Ł„ŲŗŲ§Ų” ŲŖŁ†Ų“ŁŠŲ· Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ŁŠŁ†" + +#: Shell/UsersShell.php:75 +msgid "Delete an specific user" +msgstr "Ų­Ų°Ł Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ŁŠŁ†" + +#: Shell/UsersShell.php:78 +msgid "Reset the password via email" +msgstr "Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų¹ŲØŲ± Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ" + +#: Shell/UsersShell.php:81 +msgid "Reset the password for all users" +msgstr "Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ł„ŁƒŲ§ŁŲ© Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…ŁŠŁ†" + +#: Shell/UsersShell.php:84 +msgid "Reset the password for an specific user" +msgstr "Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ł…Ų¹ŁŠŁ†" + +#: Shell/UsersShell.php:133;159 +msgid "Please enter a password." +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ ŁƒŁ„Ł…Ų© Ł…Ų±ŁˆŲ±" + +#: Shell/UsersShell.php:137 +msgid "Password changed for all users" +msgstr "ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ł„ŁƒŲ§ŁŲ© Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…ŁŠŁ†" + +#: Shell/UsersShell.php:138;166 +msgid "New password: {0}" +msgstr "ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų§Ł„Ų¬ŲÆŁŠŲÆŲ©: {0}" + +#: Shell/UsersShell.php:156;184;262;359 +msgid "Please enter a username." +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų§ŲÆŲ®Ų§Ł„ Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…." + +#: Shell/UsersShell.php:165 +msgid "Password changed for user: {0}" +msgstr "ŲŖŁ… ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ł„Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…: {0}" + +#: Shell/UsersShell.php:187 +msgid "Please enter a role." +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ ŲÆŁˆŲ±." + +#: Shell/UsersShell.php:193 +msgid "Role changed for user: {0}" +msgstr "ŲŖŁ… ŲŖŲŗŁŠŁŠŲ± Ų§Ł„ŲÆŁˆŲ± Ł„Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…: {0}" + +#: Shell/UsersShell.php:194 +msgid "New role: {0}" +msgstr "ŲÆŁˆŲ± Ų¬ŲÆŁŠŲÆ: {0}" + +#: Shell/UsersShell.php:209 +msgid "User was activated: {0}" +msgstr "ŲŖŁ… ŲŖŁ†Ų“ŁŠŲ· Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…: {0}" + +#: Shell/UsersShell.php:224 +msgid "User was de-activated: {0}" +msgstr "ŲŖŁ… Ų„Ł„ŲŗŲ§Ų” ŲŖŁ†Ų“ŁŠŲ· Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…: {0}" + +#: Shell/UsersShell.php:236 +msgid "Please enter a username or email." +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ų£Łˆ Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ." + +#: Shell/UsersShell.php:244 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"Ł…Ł† ŁŲ¶Ł„Łƒ Ų§Ų·Ł„ŲØ Ł…Ł† Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… Ų§Ł„ŲŖŲ­Ł‚Ł‚ Ł…Ł† Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ł„Ł…ŲŖŲ§ŲØŲ¹Ł‡ Ų¹Ł…Ł„ŁŠŁ‡ Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† " +"ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Shell/UsersShell.php:308 +msgid "Superuser added:" +msgstr "ŲŖŁ… Ų„Ų¶Ų§ŁŲ© SuperUser" + +#: Shell/UsersShell.php:310 +msgid "User added:" +msgstr "ŲŖŁ… Ų„Ų¶Ų§ŁŲ© Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Shell/UsersShell.php:312 +msgid "Id: {0}" +msgstr "Ų§Ł„Ł…Ų¹Ų±Ł: {0}" + +#: Shell/UsersShell.php:313 +msgid "Username: {0}" +msgstr "Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…: {0}" + +#: Shell/UsersShell.php:314 +msgid "Email: {0}" +msgstr "Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ: {0}" + +#: Shell/UsersShell.php:315 +msgid "Role: {0}" +msgstr "Ų§Ł„ŲÆŁˆŲ±: {0}" + +#: Shell/UsersShell.php:316 +msgid "Password: {0}" +msgstr "ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±: {0}" + +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "ŲŖŲ¹Ų°Ų± Ų£Ų¶Ų§ŁŁ‡ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…:" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" +msgstr "Ų§Ł„Ų­Ł‚Ł„: {0} Ų®Ų·Ų§: {1}" + +#: Shell/UsersShell.php:337 +msgid "The user was not found." +msgstr "Ł„Ł… ŁŠŲŖŁ… Ų§Ł„Ų¹Ų«ŁˆŲ± Ų¹Ł„ŁŠ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…." + +#: Shell/UsersShell.php:367 +msgid "The user {0} was not deleted. Please try again" +msgstr "Ł„Ł… ŁŠŲŖŁ… Ų­Ų°Ł Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… {0}. Ų§Ł„Ų±Ų¬Ų§Ų” Ų§Ł„Ł…Ų­Ų§ŁˆŁ„Ų© Ł…Ų±Ł‡ Ų£Ų®Ų±Ł‰" + +#: Shell/UsersShell.php:369 +msgid "The user {0} was deleted successfully" +msgstr "ŲŖŁ… Ų­Ų°Ł Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… {0} ŲØŁ†Ų¬Ų§Ų­" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Ł…Ų±Ų­ŲØŲ§ {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Ų£Ų¹ŲÆ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ł…Ł† Ł‡Ł†Ų§" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Ų„Ų°Ų§ Ł„Ł… ŁŠŲŖŁ… Ų¹Ų±Ų¶ Ų§Ł„Ų±Ų§ŲØŲ· ŲØŲ“ŁƒŁ„ ŲµŲ­ŁŠŲ­ ŲŒ Ų§Ł„Ų±Ų¬Ų§Ų” Ł†Ų³Ų® Ų§Ł„Ų¹Ł†ŁˆŲ§Ł† Ų§Ł„ŲŖŲ§Ł„ŁŠ ŁŁŠ Ł…Ų³ŲŖŲ¹Ų±Ų¶ ŁˆŁŠŲØ " +"{0}" + +#: Template/Email/html/reset_password.ctp:34 +#: Template/Email/html/social_account_validation.ctp:39 +#: Template/Email/html/validation.ctp:34 +#: Template/Email/text/reset_password.ctp:28 +#: Template/Email/text/social_account_validation.ctp:30 +#: Template/Email/text/validation.ctp:28 +msgid "Thank you" +msgstr "Ų“ŁƒŲ±Ų§Ł‹ Ł„Łƒ" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "ŲŖŁŲ¹ŁŠŁ„ ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„ ŲØŲ§Ų³ŲŖŲ®ŲÆŲ§Ł… Ų“ŲØŁƒŲ§ŲŖ Ų§Ł„ŲŖŁˆŲ§ŲµŁ„ Ų§Ł„Ų§Ų¬ŲŖŁ…Ų§Ų¹ŁŠŲ§" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "ŲŖŁŲ¹ŁŠŁ„ Ų­Ų³Ų§ŲØŁƒ Ł…Ł† Ł‡Ł†Ų§" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ł†Ų³Ų® Ų§Ł„Ų¹Ł†ŁˆŲ§Ł† Ų§Ł„ŲŖŲ§Ł„ŁŠ ŁŁŠ Ł…Ų³ŲŖŲ¹Ų±Ų¶ ŁˆŁŠŲØ {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ł†Ų³Ų® Ų§Ł„Ų¹Ł†ŁˆŲ§Ł† Ų§Ł„ŲŖŲ§Ł„ŁŠ ŁŁŠ Ł…ŲŖŲµŁŲ­ Ų§Ł„ŁˆŁŠŲØ Ų§Ł„Ų®Ų§Ųµ ŲØŁƒ Ł„ŲŖŁ†Ų“ŁŠŲ· Ų­Ų³Ų§ŲØŁƒ {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 +msgid "Actions" +msgstr "Ų§Ł„Ų§Ų¬Ų±Ų§Ų”Ų§ŲŖ" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:23 +msgid "List Users" +msgstr "Ł‚Ų§Ų¦Ł…Ų© Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…ŁŠŁ†" + +#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 +msgid "Add User" +msgstr "Ų„Ų¶Ų§ŁŲ© Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 +msgid "Username" +msgstr "Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 +msgid "Email" +msgstr "Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ" + +#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 +msgid "Password" +msgstr "ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 +msgid "First name" +msgstr "Ų§Ł„Ų§Ų³Ł… Ų§Ł„Ų£ŁˆŁ„" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 +msgid "Last name" +msgstr "Ų§Ł„Ų§Ų³Ł… Ų§Ł„Ų£Ų®ŁŠŲ±" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:49;74 +msgid "Active" +msgstr "ŁŲ¹Ų§Ł„" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Ų„Ų±Ų³Ų§Ł„" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ± Ų§Ł„Ų¬ŲÆŁŠŲÆŲ©" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "ŁƒŁ„Ł…Ł‡ Ų§Ł„Ų³Ų± Ų§Ł„Ų­Ų§Ł„ŁŠŲ©" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "ŁƒŁ„Ł…Ł‡ Ų§Ł„Ų³Ų± Ų§Ł„Ų¬ŲÆŁŠŲÆŲ©" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 +msgid "Confirm password" +msgstr "ŲŖŲ§ŁƒŁŠŲÆ ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 +msgid "Delete" +msgstr "Ų­Ų°Ł" + +#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:21 +msgid "Are you sure you want to delete # {0}?" +msgstr "Ł‡Ł„ ŲŖŲ±ŁŠŲÆ ŲØŲ§Ł„ŲŖŲ§ŁƒŁŠŲÆ Ų­Ų°Ł # {0} ŲŸ" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "ŲŖŲ¹ŲÆŁŠŁ„ Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 +msgid "Token" +msgstr "Ų§Ł„Ų±Ł…Ų² Token" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Ų§Ł†ŲŖŁ‡Ų§Ų” ŲµŁ„Ų§Ų­ŁŠŁ‡ Ų§Ł„Ų±Ł…Ų² Token" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "API token" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "ŲŖŲ§Ų±ŁŠŲ® Ų§Ł„ŲŖŁŲ¹ŁŠŁ„" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "ŲŖŲ§Ų±ŁŠŲ® Ų§Ł„Ł…ŁˆŲ§ŁŁ‚Ų© Ų¹Ł„Ł‰ Ų“Ų±ŁˆŲ· Ų§Ł„Ų§Ų³ŲŖŲ®ŲÆŲ§Ł…" + +#: Template/Users/edit.ctp:63 +msgid "Reset Google Authenticator Token" +msgstr "Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† Ų±Ł…Ų² Ł…ŲµŲ§ŲÆŁ‚Ł‡ Google" + +#: Template/Users/edit.ctp:69 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "Ł‡Ł„ ŲŖŲ±ŁŠŲÆ ŲØŲ§Ł„ŲŖŲ§ŁƒŁŠŲÆ Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† Token Ł„Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… \"{0}\" ŲŸ" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "{0} Ų¬ŲÆŁŠŲÆ" + +#: Template/Users/index.ctp:37 +msgid "View" +msgstr "Ų¹Ų±Ų¶" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ų© Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Template/Users/index.ctp:39 +msgid "Edit" +msgstr "ŲŖŲ­Ų±ŁŠŲ±" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "Ų§Ł„Ų³Ų§ŲØŁ‚" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "Ų§Ł„ŲŖŲ§Ł„ŁŠ" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ… ŁˆŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "ŲŖŲ°ŁƒŲ±Ł†ŁŠ" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Ų§Ł„ŲŖŲ³Ų¬ŁŠŁ„" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Ų„Ų¹Ų§ŲÆŲ© ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ų© Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„ŲÆŲ®ŁˆŁ„" + +#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:27 +msgid "Change Password" +msgstr "ŲŖŲŗŁŠŁŠŲ± ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 +msgid "Social Accounts" +msgstr "Ų­Ų³Ų§ŲØŲ§ŲŖ Ų§Ł„ŲŖŁˆŲ§ŲµŁ„ Ų§Ł„Ų§Ų¬ŲŖŁ…Ų§Ų¹ŁŠ" + +#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 +msgid "Avatar" +msgstr "Ų§Ł„ŲµŁˆŲ±Ų© Ų§Ł„Ų“Ų®ŲµŁŠŲ©" + +#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 +msgid "Provider" +msgstr "Ų§Ł„Ł…Ų²ŁˆŲÆ" + +#: Template/Users/profile.ctp:44 +msgid "Link" +msgstr "Ų±Ų§ŲØŲ·" + +#: Template/Users/profile.ctp:51 +msgid "Link to {0}" +msgstr "Ų§Ł„Ų§Ų±ŲŖŲØŲ§Ų· ŲØ {0}" + +#: Template/Users/register.ctp:29 +msgid "Accept TOS conditions?" +msgstr "Ł‡Ł„ ŲŖŁ‚ŲØŁ„ Ų“Ų±ŁˆŲ· Ų§Ł„Ų§Ų³ŲŖŲ®ŲÆŲ§Ł… ŲŸ" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Ų§Ł„Ų±Ų¬Ų§Ų” Ų„ŲÆŲ®Ų§Ł„ ŲØŲ±ŁŠŲÆŁƒ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ł„Ų£Ų¹Ų§ŲÆŁ‡ ŲŖŲ¹ŁŠŁŠŁ† ŁƒŁ„Ł…Ł‡ Ų§Ł„Ł…Ų±ŁˆŲ±" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Ų£Ų¹Ų§ŲÆŲ© ŲŖŁ†Ų“ŁŠŲ· Ų§Ł„Ų­Ų³Ų§ŲØ Ų¹ŲØŲ± Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "Ų§Ł„ŲØŲ±ŁŠŲÆ Ų§Ł„ŁƒŲŖŲ±ŁˆŁ†ŁŠ Ų£Łˆ Ų§Ų³Ł… Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Template/Users/verify.ctp:13 +msgid "Verification Code" +msgstr "Ų±Ł…Ų² Ų§Ł„ŲŖŲ­Ł‚Ł‚" + +#: Template/Users/verify.ctp:15 +msgid "" +" " +"Verify" +msgstr "" +" " +"ŲŖŲ£ŁƒŁŠŲÆ Ų§Ł„ŲŖŲ­Ł‚Ł‚" + +#: Template/Users/view.ctp:19 +msgid "Delete User" +msgstr "Ų­Ų°Ł Ų§Ł„Ł…Ų³ŲŖŲ®ŲÆŁ…" + +#: Template/Users/view.ctp:24 +msgid "New User" +msgstr "Ł…Ų³ŲŖŲ®ŲÆŁ… Ų¬ŲÆŁŠŲÆ" + +#: Template/Users/view.ctp:31 +msgid "Id" +msgstr "Ų§Ł„Ł…Ų¹Ų±Ł" + +#: Template/Users/view.ctp:37 +msgid "First Name" +msgstr "Ų§Ł„Ų§Ų³Ł… Ų§Ł„Ų§ŁˆŁ„" + +#: Template/Users/view.ctp:39 +msgid "Last Name" +msgstr "Ų§Ł„Ų§Ų³Ł… Ų§Ł„Ų§Ų®ŁŠŲ±" + +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "Ų§Ł„ŲÆŁˆŲ±" + +#: Template/Users/view.ctp:45 +msgid "Api Token" +msgstr "API token" + +#: Template/Users/view.ctp:53 +msgid "Token Expires" +msgstr "Token Expires" + +#: Template/Users/view.ctp:55 +msgid "Activation Date" +msgstr "ŲŖŲ§Ų±ŁŠŲ® Ų§Ł„ŲŖŁŲ¹ŁŠŁ„" + +#: Template/Users/view.ctp:57 +msgid "Tos Date" +msgstr "ŲŖŲ§Ų±ŁŠŲ® Ų§Ł„Ł…ŁˆŲ§ŁŁ‚Ų© Ų¹Ł„Ł‰ Ų“Ų±ŁˆŲ· Ų§Ł„Ų§Ų³ŲŖŲ®ŲÆŲ§Ł…" + +#: Template/Users/view.ctp:59;75 +msgid "Created" +msgstr "ŲŖŲ§Ų±ŁŠŲ® Ų§Ł„Ų„ŲŖŲ“Ų§Ų”" + +#: Template/Users/view.ctp:61;76 +msgid "Modified" +msgstr "Ų§Ų®Ų± ŲŖŲ¹ŲÆŁŠŁ„" + +#: View/Helper/UserHelper.php:45 +msgid "Sign in with" +msgstr "ŲÆŲ®ŁˆŁ„ ŲØŲ§Ų³ŲŖŲ®ŲÆŲ§Ł…" + +#: View/Helper/UserHelper.php:48 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:57 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:106 +msgid "Logout" +msgstr "ŲŖŲ³Ų¬ŁŠŁ„ Ų§Ł„Ų®Ų±ŁˆŲ¬" + +#: View/Helper/UserHelper.php:123 +msgid "Welcome, {0}" +msgstr "Ł…Ų±Ų­ŲØŲ§ ŲŒ {0}" + +#: View/Helper/UserHelper.php:146 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "Ł„Ł… ŁŠŲŖŁ… Ų¶ŲØŲ· Ų§Ų¹ŲÆŲ§ŲÆŲ§ŲŖ reCaptcha! Ų§Ł„Ų±Ų¬Ų§Ų” Ų„Ų¶Ų§ŁŲ© Ų§Ų¹ŲÆŲ§ŲÆŲ§ŲŖ Users.reCaptcha.key" + +#: View/Helper/UserHelper.php:205 +msgid "btn btn-social btn-{0}" +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:211 +msgid "Connected with {0}" +msgstr "Ł…ŲŖŲµŁ„ ŲØ {0}" + +#: View/Helper/UserHelper.php:216 +msgid "Connect with {0}" +msgstr "Ų§Ł„Ų§ŲŖŲµŲ§Ł„ ŲØ {0}" diff --git a/src/Locale/es/Users.mo b/src/Locale/es/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..50edf1e2bd033c310ec6e9f4fe7a3a8d25ed92d0 GIT binary patch literal 15243 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 literal 0 HcmV?d00001 diff --git a/src/Locale/es/Users.po b/src/Locale/es/Users.po new file mode 100644 index 000000000..16f4de825 --- /dev/null +++ b/src/Locale/es/Users.po @@ -0,0 +1,854 @@ +# LANGUAGE translation of CakePHP Application +# Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com) +# +msgid "" +msgstr "" +"Project-Id-Version: CakeDC Users\n" +"POT-Creation-Date: 2016-10-26 09:23+0000\n" +"PO-Revision-Date: 2017-05-29 16:50+0100\n" +"Last-Translator: Bernat Arlandis \n" +"Language-Team: CakeDC \n" +"Language: es_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.6.10\n" +"X-Poedit-SourceCharset: UTF-8\n" + +#: Auth/ApiKeyAuthenticate.php:73 +msgid "Type {0} is not valid" +msgstr "El tipo {0} no es vĆ”lido" + +#: Auth/ApiKeyAuthenticate.php:77 +msgid "Type {0} has no associated callable" +msgstr "El tipo {0} no tiene un invocable asociado" + +#: Auth/ApiKeyAuthenticate.php:86 +msgid "SSL is required for ApiKey Authentication" +msgstr "SSL requerido para autenticaciĆ³n por ApiKey" + +#: Auth/SimpleRbacAuthorize.php:142 +msgid "" +"Missing configuration file: \"config/{0}.php\". Using default permissions" +msgstr "" +"Falta el archivo de configuraciĆ³n: \"config/{0}.php\". Utilizando permisos " +"predeterminados" + +#: Auth/SocialAuthenticate.php:432 +msgid "Provider cannot be empty" +msgstr "El proveedor no puede ser vacĆ­o" + +#: Auth/Rules/AbstractRule.php:78 +msgid "" +"Table alias is empty, please define a table alias, we could not extract a " +"default table from the request" +msgstr "" +"El alias de la tabla estĆ” vacĆ­o, por favor define un alias para la tabla ya " +"que no podemos establecer una tabla predeterminada de la peticiĆ³n" + +#: Auth/Rules/Owner.php:67;70 +msgid "" +"Missing column {0} in table {1} while checking ownership permissions for " +"user {2}" +msgstr "" +"La columna {0} de la tabla {1} no existe, estĆ”bamos comprobando el permiso " +"de propietario para el usuario {2}" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Cuenta validada correctamente" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "No se pudo validar la cuenta" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Token o cuenta social incorrecta" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "Cuenta social ya activa" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "No se pudo validar la cuenta social " + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "Email enviado correctamente" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "No se puede enviar el email" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "Cuenta invĆ”lida" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "No se puede reenviar el Email" + +#: Controller/Component/RememberMeComponent.php:69 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "App salt invĆ”lido, debe contener al menos 256 bits (32 bytes)" + +#: Controller/Component/UsersAuthComponent.php:178 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"No es posible activar el flujo de trabajo para la validaciĆ³n de email si " +"use_mail es falso" + +#: Controller/Traits/LoginTrait.php:96 +msgid "Issues trying to log in with your social account" +msgstr "Hubo un problema al iniciar sesiĆ³n con tu cuenta social" + +#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Por favor, introduce tu email" + +#: Controller/Traits/LoginTrait.php:108 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"El usuario no se ha validado todavĆ­a. Instrucciones enviadas a tu bandeja de " +"entrada" + +#: Controller/Traits/LoginTrait.php:110 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"La cuenta social no se ha validado todavĆ­a. Instrucciones enviadas a tu " +"bandeja de entrada" + +#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 +msgid "Invalid reCaptcha" +msgstr "El cĆ³digo reCaptcha no es vĆ”lido" + +#: Controller/Traits/LoginTrait.php:171 +msgid "You are already logged in" +msgstr "Ya has iniciado sesiĆ³n" + +#: Controller/Traits/LoginTrait.php:217 +msgid "Username or password is incorrect" +msgstr "Usuario o contraseƱa incorrecta" + +#: Controller/Traits/LoginTrait.php:238 +msgid "You've successfully logged out" +msgstr "SesiĆ³n finalizada correctamente" + +#: Controller/Traits/PasswordManagementTrait.php:47;76 +#: Controller/Traits/ProfileTrait.php:49 +msgid "User was not found" +msgstr "Usuario no encontrado" + +#: Controller/Traits/PasswordManagementTrait.php:64;72;80 +msgid "Password could not be changed" +msgstr "No es posible cambiar la contraseƱa" + +#: Controller/Traits/PasswordManagementTrait.php:68 +msgid "Password has been changed successfully" +msgstr "ContraseƱa cambiada correctamente" + +#: Controller/Traits/PasswordManagementTrait.php:78 +msgid "{0}" +msgstr "{0}" + +#: Controller/Traits/PasswordManagementTrait.php:120 +msgid "Please check your email to continue with password reset process" +msgstr "" +"Por favor, comprueba tu correo para continuar con el proceso de " +"restablecimiento de contraseƱa" + +#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 +msgid "The password token could not be generated. Please try again" +msgstr "" +"No se pudo generar el token de contraseƱa. Por favor, intĆ©ntalo de nuevo" + +#: Controller/Traits/PasswordManagementTrait.php:129 +#: Controller/Traits/UserValidationTrait.php:100 +msgid "User {0} was not found" +msgstr "Usuario {0} no encontrado" + +#: Controller/Traits/PasswordManagementTrait.php:131 +msgid "The user is not active" +msgstr "El usuario no estĆ” activo" + +#: Controller/Traits/PasswordManagementTrait.php:133 +#: Controller/Traits/UserValidationTrait.php:95;104 +msgid "Token could not be reset" +msgstr "No se puede restablecer el token" + +#: Controller/Traits/ProfileTrait.php:53 +msgid "Not authorized, please login first" +msgstr "" +"No estĆ”s autorizado para realizar esta acciĆ³n, por favor inicia sesiĆ³n " +"primero" + +#: Controller/Traits/RegisterTrait.php:42 +msgid "You must log out to register a new user account" +msgstr "Debes finalizar la sesiĆ³n para registrar una nueva cuenta de usuario" + +#: Controller/Traits/RegisterTrait.php:88 +msgid "The user could not be saved" +msgstr "No se ha podido guardar el usuario" + +#: Controller/Traits/RegisterTrait.php:122 +msgid "You have registered successfully, please log in" +msgstr "Registrado correctamente, por favor inicia sesiĆ³n" + +#: Controller/Traits/RegisterTrait.php:124 +msgid "Please validate your account before log in" +msgstr "Por favor, valida tu cuenta antes de iniciar sesiĆ³n" + +#: Controller/Traits/SimpleCrudTrait.php:76;106 +msgid "The {0} has been saved" +msgstr "El {0} ha sido guardado" + +#: Controller/Traits/SimpleCrudTrait.php:80;110 +msgid "The {0} could not be saved" +msgstr "El {0} no ha podido guardarse" + +#: Controller/Traits/SimpleCrudTrait.php:130 +msgid "The {0} has been deleted" +msgstr "El {0} ha sido eliminado" + +#: Controller/Traits/SimpleCrudTrait.php:132 +msgid "The {0} could not be deleted" +msgstr "El {0} no ha podido eliminarse" + +#: Controller/Traits/SocialTrait.php:39 +msgid "The reCaptcha could not be validated" +msgstr "El cĆ³digo reCaptcha no se pudo validar" + +#: Controller/Traits/UserValidationTrait.php:42 +msgid "User account validated successfully" +msgstr "Cuenta de usuario validada correctamente" + +#: Controller/Traits/UserValidationTrait.php:44 +msgid "User account could not be validated" +msgstr "No se pudo validar la cuenta de usuario" + +#: Controller/Traits/UserValidationTrait.php:47 +msgid "User already active" +msgstr "Usuario ya activo" + +#: Controller/Traits/UserValidationTrait.php:53 +msgid "Reset password token was validated successfully" +msgstr "Restablecimiento del token de contraseƱa validado correctamente" + +#: Controller/Traits/UserValidationTrait.php:58 +msgid "Reset password token could not be validated" +msgstr "Restablecimiento del token de contraseƱa no pudo validarse" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Invalid validation type" +msgstr "Tipo de validaciĆ³n invĆ”lido" + +#: Controller/Traits/UserValidationTrait.php:65 +msgid "Invalid token or user account already validated" +msgstr "Token invĆ”lido, o tu cuenta ya habĆ­a sido validada anteriormente" + +#: Controller/Traits/UserValidationTrait.php:67 +msgid "Token already expired" +msgstr "Token ya expirado" + +#: Controller/Traits/UserValidationTrait.php:93 +msgid "Token has been reset successfully. Please check your email." +msgstr "" +"Se ha restablecido el token correctamente. Por favor comprueba tu email." + +#: Controller/Traits/UserValidationTrait.php:102 +msgid "User {0} is already active" +msgstr "El usuario {0} ya estĆ” activo" + +#: Email/EmailSender.php:39 +msgid "Your account validation link" +msgstr "Enlace para validar tu cuenta" + +#: Mailer/UsersMailer.php:55 +msgid "{0}Your reset password link" +msgstr "{0} Enlace para restablecer tu contraseƱa" + +#: Mailer/UsersMailer.php:78 +msgid "{0}Your social account validation link" +msgstr "{0} Enlace de validaciĆ³n de tu cuenta social" + +#: Model/Behavior/PasswordBehavior.php:56 +msgid "Reference cannot be null" +msgstr "La referencia no puede estar vacĆ­a" + +#: Model/Behavior/PasswordBehavior.php:61 +msgid "Token expiration cannot be empty" +msgstr "La fecha de expiraciĆ³n del Token no puede estar vacĆ­a" + +#: Model/Behavior/PasswordBehavior.php:67;116 +msgid "User not found" +msgstr "Usuario no encontrado" + +#: Model/Behavior/PasswordBehavior.php:71 +#: Model/Behavior/RegisterBehavior.php:111 +msgid "User account already validated" +msgstr "Tu usuario ya se habĆ­a validado antes" + +#: Model/Behavior/PasswordBehavior.php:78 +msgid "User not active" +msgstr "El usuario no estĆ” activo" + +#: Model/Behavior/PasswordBehavior.php:121 +msgid "The current password does not match" +msgstr "La contraseƱa actual no coincide" + +#: Model/Behavior/PasswordBehavior.php:124 +msgid "You cannot use the current password as the new one" +msgstr "No puedes usar tu contraseƱa actual como nueva contraseƱa" + +#: Model/Behavior/RegisterBehavior.php:89 +msgid "User not found for the given token and email." +msgstr "Usuario no encontrado para el token y email proporcionado" + +#: Model/Behavior/RegisterBehavior.php:92 +msgid "Token has already expired user with no token" +msgstr "El token ha expirado usuario sin token" + +#: Model/Behavior/SocialAccountBehavior.php:102;129 +msgid "Account already validated" +msgstr "Cuenta ya activada" + +#: Model/Behavior/SocialAccountBehavior.php:105;132 +msgid "Account not found for the given token and email." +msgstr "Cuenta no encontrada para el token y email proporcionado" + +#: Model/Behavior/SocialBehavior.php:56 +msgid "Unable to login user with reference {0}" +msgstr "No se puede iniciar sesiĆ³n con el usuario con referencia {0}" + +#: Model/Behavior/SocialBehavior.php:98 +msgid "Email not present" +msgstr "No se encuentra el email" + +#: Model/Table/UsersTable.php:82 +msgid "Your password does not match your confirm password. Please try again" +msgstr "" +"La contraseƱa y la comprobaciĆ³n no concuerdan. Por favor intĆ©ntalo de nuevo" + +#: Model/Table/UsersTable.php:175 +msgid "Username already exists" +msgstr "Nombre de usuario ya existente" + +#: Model/Table/UsersTable.php:181 +msgid "Email already exists" +msgstr "Email ya existente" + +#: Model/Table/UsersTable.php:214 +msgid "Missing 'username' in options data" +msgstr "Falta 'username' en las opciones" + +#: Shell/UsersShell.php:54 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Utilidades para CakeDC Users Plugin" + +#: Shell/UsersShell.php:55 +msgid "Activate an specific user" +msgstr "Activar un usuario especĆ­fico" + +#: Shell/UsersShell.php:56 +msgid "Add a new superadmin user for testing purposes" +msgstr "AƱadir un nuevo superadmin" + +#: Shell/UsersShell.php:57 +msgid "Add a new user" +msgstr "AƱadir un nuevo usuario" + +#: Shell/UsersShell.php:58 +msgid "Change the role for an specific user" +msgstr "Cambiar el rol de un usuario especĆ­fico" + +#: Shell/UsersShell.php:59 +msgid "Deactivate an specific user" +msgstr "Desactivar un usuario" + +#: Shell/UsersShell.php:60 +msgid "Delete an specific user" +msgstr "Borrar un usuario" + +#: Shell/UsersShell.php:61 +msgid "Reset the password via email" +msgstr "Restablecer la contraseƱa vĆ­a email" + +#: Shell/UsersShell.php:62 +msgid "Reset the password for all users" +msgstr "Restablecer la contraseƱa de todos los usuarios" + +#: Shell/UsersShell.php:63 +msgid "Reset the password for an specific user" +msgstr "Restablecer la contraseƱa de un usuario concreto" + +#: Shell/UsersShell.php:98 +msgid "User added:" +msgstr "Usuario aƱadido:" + +#: Shell/UsersShell.php:99;127 +msgid "Id: {0}" +msgstr "Id: {0}" + +#: Shell/UsersShell.php:100;128 +msgid "Username: {0}" +msgstr "Nombre de usuario: {0}" + +#: Shell/UsersShell.php:101;129 +msgid "Email: {0}" +msgstr "Email: {0}" + +#: Shell/UsersShell.php:102;130 +msgid "Password: {0}" +msgstr "ContraseƱa: {0}" + +#: Shell/UsersShell.php:126 +msgid "Superuser added:" +msgstr "Superusuario aƱadido:" + +#: Shell/UsersShell.php:132 +msgid "Superuser could not be added:" +msgstr "No se pudo aƱadir un superusuario:" + +#: Shell/UsersShell.php:135 +msgid "Field: {0} Error: {1}" +msgstr "Campo: {0} Error: {1}" + +#: Shell/UsersShell.php:153;179 +msgid "Please enter a password." +msgstr "Por favor, introduce una contraseƱa." + +#: Shell/UsersShell.php:157 +msgid "Password changed for all users" +msgstr "ContraseƱa cambiada para todos los usuarios" + +#: Shell/UsersShell.php:158;186 +msgid "New password: {0}" +msgstr "Nueva contraseƱa: {0}" + +#: Shell/UsersShell.php:176;204;282;324 +msgid "Please enter a username." +msgstr "Por favor introduce el nombre de usuario." + +#: Shell/UsersShell.php:185 +msgid "Password changed for user: {0}" +msgstr "ContraseƱa cambiada para el usuario: {0}" + +#: Shell/UsersShell.php:207 +msgid "Please enter a role." +msgstr "Por favor introduce el rol." + +#: Shell/UsersShell.php:213 +msgid "Role changed for user: {0}" +msgstr "Rol cambiado para el usuario: {0}" + +#: Shell/UsersShell.php:214 +msgid "New role: {0}" +msgstr "Nuevo rol: {0}" + +#: Shell/UsersShell.php:229 +msgid "User was activated: {0}" +msgstr "Usuario activado: {0}" + +#: Shell/UsersShell.php:244 +msgid "User was de-activated: {0}" +msgstr "Usuario desactivado: {0}" + +#: Shell/UsersShell.php:256 +msgid "Please enter a username or email." +msgstr "Por favor introduce el nombre de usuario o email." + +#: Shell/UsersShell.php:264 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"Por favor, pide al usuario que mire su buzĆ³n de correo para continuar con el " +"proceso de restablecimiento de su contraseƱa" + +#: Shell/UsersShell.php:302 +msgid "The user was not found." +msgstr "Usuario no encontrado." + +#: Shell/UsersShell.php:332 +msgid "The user {0} was not deleted. Please try again" +msgstr "El usuario {0} no ha sido borrado. IntĆ©ntalo de nuevo por favor" + +#: Shell/UsersShell.php:334 +msgid "The user {0} was deleted successfully" +msgstr "El usuario {0} se borrĆ³ correctamente" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Hola {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Restablece tu contraseƱa aquĆ­" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correcly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Por favor, copia la siguiente direcciĆ³n en tu navegador si el enlace no se " +"ve correctamente {0}" + +#: Template/Email/html/reset_password.ctp:30 +#: Template/Email/html/social_account_validation.ctp:35 +#: Template/Email/html/validation.ctp:30 +#: Template/Email/text/reset_password.ctp:24 +#: Template/Email/text/social_account_validation.ctp:26 +#: Template/Email/text/validation.ctp:24 +msgid "Thank you" +msgstr "Gracias" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Activa tu acceso social aquĆ­" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Activa tu cuenta aquĆ­" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Por favor copia la siguiente direcciĆ³n en tu navegador {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"Por favor copia la siguiente direcciĆ³n en tu navegador para activar tu " +"acceso social {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 +msgid "Actions" +msgstr "Acciones" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 +#: Template/Users/view.ctp:19 +msgid "List Users" +msgstr "Listar Usuarios" + +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:21 +msgid "List Accounts" +msgstr "Listar Cuentas" + +#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 +msgid "Add User" +msgstr "AƱadir Usuario" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 +#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 +msgid "Username" +msgstr "Usuario" + +#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 +msgid "Email" +msgstr "Email" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 +msgid "First name" +msgstr "Nombre" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 +msgid "Last name" +msgstr "Apellidos" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:44;75 +msgid "Active" +msgstr "Activo" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Enviar" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Por favor introduce la nueva contraseƱa" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "ContraseƱa actual" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Nueva contraseƱa" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 +msgid "Confirm password" +msgstr "Confirmar contraseƱa" + +#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:101 +msgid "Delete" +msgstr "Eliminar" + +#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:18;101 +msgid "Are you sure you want to delete # {0}?" +msgstr "ĀæEstĆ” seguro de que quieres eliminar # {0}?" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Editar Usuario" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 +msgid "Token" +msgstr "Token" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Token caduca" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "Api Token" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Fecha de activaciĆ³n" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "Fecha TOS" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Nuevo {0}" + +#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 +msgid "View" +msgstr "Ver" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Cambiar contraseƱa" + +#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 +msgid "Edit" +msgstr "Editar" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "anterior" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "siguiente" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Por favor introduce tu usuario y contraseƱa" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "RecuĆ©rdame" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Registrarse" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Cambiar contraseƱa" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "Iniciar sesiĆ³n" + +#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:24 +msgid "Change Password" +msgstr "Cambiar contraseƱa" + +#: Template/Users/profile.ctp:34 +msgid "Social Accounts" +msgstr "Cuentas sociales" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 +msgid "Avatar" +msgstr "Avatar" + +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 +msgid "Provider" +msgstr "Proveedor" + +#: Template/Users/profile.ctp:40 +msgid "Link" +msgstr "Enlace" + +#: Template/Users/profile.ctp:47 +msgid "Link to {0}" +msgstr "Enlace a {0}" + +#: Template/Users/register.ctp:20 +msgid "Password" +msgstr "ContraseƱa" + +#: Template/Users/register.ctp:28 +msgid "Accept TOS conditions?" +msgstr "ĀæAceptas las condiciones del servicios?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Por favor introduce tu email para restablecer tu contraseƱa" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Reenviar email de validaciĆ³n" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "Email o usuario" + +#: Template/Users/view.ctp:18 +msgid "Delete User" +msgstr "Eliminar Usuario" + +#: Template/Users/view.ctp:20 +msgid "New User" +msgstr "Nuevo Usuario" + +#: Template/Users/view.ctp:28;67 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:34 +msgid "First Name" +msgstr "Nombre" + +#: Template/Users/view.ctp:36 +msgid "Last Name" +msgstr "Apellidos" + +#: Template/Users/view.ctp:40 +msgid "Api Token" +msgstr "Api Token" + +#: Template/Users/view.ctp:48;74 +msgid "Token Expires" +msgstr "Token caduca" + +#: Template/Users/view.ctp:50 +msgid "Activation Date" +msgstr "Fecha de activaciĆ³n" + +#: Template/Users/view.ctp:52 +msgid "Tos Date" +msgstr "Fecha Tos" + +#: Template/Users/view.ctp:54;77 +msgid "Created" +msgstr "Creado" + +#: Template/Users/view.ctp:56;78 +msgid "Modified" +msgstr "Modificado" + +#: Template/Users/view.ctp:63 +msgid "Related Accounts" +msgstr "Cuentas relacionadas" + +#: Template/Users/view.ctp:68 +msgid "User Id" +msgstr "Id Usuario" + +#: Template/Users/view.ctp:71 +msgid "Reference" +msgstr "Referencia" + +#: Template/Users/view.ctp:76 +msgid "Data" +msgstr "Datos" + +#: View/Helper/UserHelper.php:46 +msgid "Sign in with" +msgstr "Iniciar sesiĆ³n con" + +#: View/Helper/UserHelper.php:49 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:52 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0}" + +#: View/Helper/UserHelper.php:91 +msgid "Logout" +msgstr "Salir" + +#: View/Helper/UserHelper.php:108 +msgid "Welcome, {0}" +msgstr "Bienvenido/a, {0}" + +#: View/Helper/UserHelper.php:131 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"reCaptcha no se ha configurado, por favor configura Users.reCaptcha.key" + +#: Model/Behavior/RegisterBehavior.php:148 +msgid "This field is required" +msgstr "Este campo es requerido" + +#~ msgid "The old password does not match" +#~ msgstr "La antigua contraseƱa no coincide" + +#~ msgid "SocialAccount already active" +#~ msgstr "Cuenta social ya activa" + +#~ msgid "" +#~ "The social account is not active. Please check your email for " +#~ "instructions. {0}" +#~ msgstr "" +#~ "La cuenta social estĆ” inactiva. Por favor, compruebe las instrucciones en " +#~ "su correo. {0}" + +#~ msgid "There was an error associating your social network account" +#~ msgstr "Hubo un error al asociar su cuenta de la red social" + +#~ msgid "Invalid token and/or email" +#~ msgstr "Token y/o email invĆ”lido" + +#~ msgid "The \"tos\" property is not present" +#~ msgstr "La propiedad \"tos\" no estĆ” presente" + +#~ msgid "+ {0} secs" +#~ msgstr "+ {0} secs" + +#~ msgid "Sign in with Facebook" +#~ msgstr "Login con Facebook" + +#~ msgid "Sign in with Twitter" +#~ msgstr "Login con Twitter" diff --git a/src/Locale/fr_FR/Users.mo b/src/Locale/fr_FR/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..fc623371daeb2249909fa3fc2f7b26a62cfd7179 GIT binary patch literal 16147 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 m)S@zb^pX0=9|Ro}3T\n" +"Language-Team: CakeDC \n" +"Language: fr_FR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 1.8.11\n" + +#: Auth/ApiKeyAuthenticate.php:73 +msgid "Type {0} is not valid" +msgstr "Le type {0} est invalide" + +#: Auth/ApiKeyAuthenticate.php:77 +msgid "Type {0} has no associated callable" +msgstr "Le type {0} n'a aucune fonction de rappel associĆ©e" + +#: Auth/ApiKeyAuthenticate.php:86 +msgid "SSL is required for ApiKey Authentication" +msgstr "SSL est requis pour ApiKey Authentication" + +#: Auth/SimpleRbacAuthorize.php:142 +msgid "" +"Missing configuration file: \"config/{0}.php\". Using default permissions" +msgstr "" +"Fichier de configuration manquant : \"config/{0}.php\". Utilisation des " +"permissions par dĆ©faut" + +#: Auth/SocialAuthenticate.php:432 +msgid "Provider cannot be empty" +msgstr "Le fournisseur ne peut pas ĆŖtre vide" + +#: Auth/Rules/AbstractRule.php:78 +msgid "" +"Table alias is empty, please define a table alias, we could not extract a " +"default table from the request" +msgstr "" +"L'alias de table est vide, merci de dĆ©finir un alias de table, nous ne " +"pouvons pas extraire une table par dĆ©faut depuis la requĆŖte" + +#: Auth/Rules/Owner.php:67;70 +msgid "" +"Missing column {0} in table {1} while checking ownership permissions for " +"user {2}" +msgstr "" +"Colonne {0} manquante dans la table {1} lors de la vĆ©rification des " +"autorisations de propriĆ©tĆ© pour l'utilisateur {2}" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Le compte a Ć©tĆ© validĆ© avec succĆØs" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "Le compte n'a pas pu ĆŖtre validĆ©" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Jeton et/ou compte de rĆ©seau social invalide" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "Compte de rĆ©seau social dĆ©jĆ  actif" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "Le compte de rĆ©seau social n'a pas pu ĆŖtre validĆ©" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "Courriel envoyĆ© avec succĆØs" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "Le courriel n'a pas pu ĆŖtre envoyĆ©" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "Compte invalide" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "Le courriel n'a pas pu ĆŖtre rĆ©envoyĆ©" + +#: Controller/Component/RememberMeComponent.php:69 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" +"ClĆ© de salage de l'application invalide, la clĆ© de salage de l'application " +"doit-ĆŖtre d'une longueur minimale de 256 bits (32 octets)" + +#: Controller/Component/UsersAuthComponent.php:178 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"Vous ne pouvez pas activer le processus de validation par courriel si " +"use_email est dĆ©fini Ć  false" + +#: Controller/Traits/LoginTrait.php:96 +msgid "Issues trying to log in with your social account" +msgstr "" +"Un problĆØme est survu lors de la tentative d'identification avec votre " +"compte de rĆ©seau social" + +#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Merci d'entrer votre email" + +#: Controller/Traits/LoginTrait.php:108 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Votre compte n'a pas encore Ć©tĆ© validĆ©. Merci de vĆ©rifier votre boĆ®te de " +"rĆ©ception pour obtenir les instructions" + +#: Controller/Traits/LoginTrait.php:110 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Votre compte de rĆ©seau social n'a pas encore Ć©tĆ© validĆ©. Merci de vĆ©rifier " +"votre boĆ®te de rĆ©ception pour obtenir les instructions" + +#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 +msgid "Invalid reCaptcha" +msgstr "La validation reCaptcha a Ć©chouĆ©" + +#: Controller/Traits/LoginTrait.php:171 +msgid "You are already logged in" +msgstr "Vous ĆŖtes dĆ©jĆ  identifiĆ©" + +#: Controller/Traits/LoginTrait.php:217 +msgid "Username or password is incorrect" +msgstr "Le nom d'utilisateur ou le mot de passe est incorrect" + +#: Controller/Traits/LoginTrait.php:238 +msgid "You've successfully logged out" +msgstr "Vous avez Ć©tĆ© correctement dĆ©connectĆ©" + +#: Controller/Traits/PasswordManagementTrait.php:47;76 +#: Controller/Traits/ProfileTrait.php:49 +msgid "User was not found" +msgstr "L'utilisateur n'a pas Ć©tĆ© trouvĆ©" + +#: Controller/Traits/PasswordManagementTrait.php:64;72;80 +msgid "Password could not be changed" +msgstr "Le mot de passe n'a pas pu ĆŖtre changĆ©" + +#: Controller/Traits/PasswordManagementTrait.php:68 +msgid "Password has been changed successfully" +msgstr "Le mot de passe a Ć©tĆ© changĆ© avec succĆØs" + +#: Controller/Traits/PasswordManagementTrait.php:78 +msgid "{0}" +msgstr "{0}" + +#: Controller/Traits/PasswordManagementTrait.php:120 +msgid "Please check your email to continue with password reset process" +msgstr "" +"Merci de vĆ©rifier vos courriels pour poursuivre la procĆ©dure de " +"rĆ©initialisation du mot de passe" + +#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 +msgid "The password token could not be generated. Please try again" +msgstr "Le jeton du mot de passe n'a pas pu ĆŖtre gĆ©nĆ©rĆ©. Veuillez rĆ©essayer" + +#: Controller/Traits/PasswordManagementTrait.php:129 +#: Controller/Traits/UserValidationTrait.php:100 +msgid "User {0} was not found" +msgstr "L'utilisateur {0} n'a pas Ć©tĆ© trouvĆ©" + +#: Controller/Traits/PasswordManagementTrait.php:131 +msgid "The user is not active" +msgstr "L'utilisateur n'est pas actif" + +#: Controller/Traits/PasswordManagementTrait.php:133 +#: Controller/Traits/UserValidationTrait.php:95;104 +msgid "Token could not be reset" +msgstr "Le jeton n'a pas pu ĆŖtre rĆ©initialisĆ©" + +#: Controller/Traits/ProfileTrait.php:53 +msgid "Not authorized, please login first" +msgstr "Non autorisĆ©, merci de vous identifier d'abord" + +#: Controller/Traits/RegisterTrait.php:42 +msgid "You must log out to register a new user account" +msgstr "" +"Vous devez vous dĆ©connecter pour enregistrer un nouveau compte utilisateur" + +#: Controller/Traits/RegisterTrait.php:88 +msgid "The user could not be saved" +msgstr "L'utilisateur n'a pas pu ĆŖtre sauvegardĆ©" + +#: Controller/Traits/RegisterTrait.php:122 +msgid "You have registered successfully, please log in" +msgstr "Vous ĆŖtes dĆ©sormais enregistrĆ©, merci de vous identifier" + +#: Controller/Traits/RegisterTrait.php:124 +msgid "Please validate your account before log in" +msgstr "Merci de valider votre compte avant de vous identifier" + +#: Controller/Traits/SimpleCrudTrait.php:76;106 +msgid "The {0} has been saved" +msgstr "Le {0} a Ć©tĆ© sauvegardĆ©" + +#: Controller/Traits/SimpleCrudTrait.php:80;110 +msgid "The {0} could not be saved" +msgstr "Le {0} n'a pas pu ĆŖtre sauvegardĆ©" + +#: Controller/Traits/SimpleCrudTrait.php:130 +msgid "The {0} has been deleted" +msgstr "Le {0} a Ć©tĆ© supprimĆ©" + +#: Controller/Traits/SimpleCrudTrait.php:132 +msgid "The {0} could not be deleted" +msgstr "Le {0} n'a pas pu ĆŖtre supprimĆ©" + +#: Controller/Traits/SocialTrait.php:39 +msgid "The reCaptcha could not be validated" +msgstr "Le reCaptcha n'a pas pu ĆŖtre validĆ©" + +#: Controller/Traits/UserValidationTrait.php:42 +msgid "User account validated successfully" +msgstr "Compte utilisateur validĆ© avec succĆØs" + +#: Controller/Traits/UserValidationTrait.php:44 +msgid "User account could not be validated" +msgstr "Le compte utilisateur n'a pas pu ĆŖtre validĆ©" + +#: Controller/Traits/UserValidationTrait.php:47 +msgid "User already active" +msgstr "Utilisateur dĆ©jĆ  actif" + +#: Controller/Traits/UserValidationTrait.php:53 +msgid "Reset password token was validated successfully" +msgstr "Le jeton de rĆ©initialisation du mot de passe a Ć©tĆ© validĆ© avec succĆØs" + +#: Controller/Traits/UserValidationTrait.php:58 +msgid "Reset password token could not be validated" +msgstr "Le jeton de rĆ©initialisation du mot de passe n'a pas pu ĆŖtre validĆ©" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Invalid validation type" +msgstr "Type de validation invalide" + +#: Controller/Traits/UserValidationTrait.php:65 +msgid "Invalid token or user account already validated" +msgstr "Jeton invalide ou compte utilisateur dĆ©jĆ  activĆ©" + +#: Controller/Traits/UserValidationTrait.php:67 +msgid "Token already expired" +msgstr "Le jeton a dĆ©jĆ  expirĆ©" + +#: Controller/Traits/UserValidationTrait.php:93 +msgid "Token has been reset successfully. Please check your email." +msgstr "" +"Le jeton a Ć©tĆ© rĆ©initialisĆ© avec succĆØs. Veuillez consulter vos courriels." + +#: Controller/Traits/UserValidationTrait.php:102 +msgid "User {0} is already active" +msgstr "L'utilisateur {0} est dĆ©jĆ  actif" + +#: Email/EmailSender.php:39 +msgid "Your account validation link" +msgstr "Votre lien de validation de compte" + +#: Mailer/UsersMailer.php:55 +msgid "{0}Your reset password link" +msgstr "{0}Votre lien de rĆ©initialisation de mot de passe" + +#: Mailer/UsersMailer.php:78 +msgid "{0}Your social account validation link" +msgstr "{0}Votre lien de validation de compte social" + +#: Model/Behavior/PasswordBehavior.php:56 +msgid "Reference cannot be null" +msgstr "La rĆ©fĆ©rence ne peut pas ĆŖtre nulle" + +#: Model/Behavior/PasswordBehavior.php:61 +msgid "Token expiration cannot be empty" +msgstr "L'expiration du jeton ne peut pas ĆŖtre vide" + +#: Model/Behavior/PasswordBehavior.php:67;116 +msgid "User not found" +msgstr "Utilisateur non trouvĆ©" + +#: Model/Behavior/PasswordBehavior.php:71 +#: Model/Behavior/RegisterBehavior.php:111 +msgid "User account already validated" +msgstr "Compte utilisateur dĆ©jĆ  validĆ©" + +#: Model/Behavior/PasswordBehavior.php:78 +msgid "User not active" +msgstr "Utilisateur non activĆ©" + +#: Model/Behavior/PasswordBehavior.php:121 +msgid "The current password does not match" +msgstr "Le mot de passe actuel ne correspond pas" + +#: Model/Behavior/PasswordBehavior.php:124 +msgid "You cannot use the current password as the new one" +msgstr "" +"Vous ne pouvez pas utiliser le mot de passe actuel comme nouveau mot de passe" + +#: Model/Behavior/RegisterBehavior.php:89 +msgid "User not found for the given token and email." +msgstr "Utilisateur non trouvĆ© pour le jeton et le courriel spĆ©cifiĆ©s" + +#: Model/Behavior/RegisterBehavior.php:92 +msgid "Token has already expired user with no token" +msgstr "Le jeton a dĆ©jĆ  expirĆ© utilisateur sans jeton" + +#: Model/Behavior/SocialAccountBehavior.php:102;129 +msgid "Account already validated" +msgstr "Compte dĆ©jĆ  validĆ©" + +#: Model/Behavior/SocialAccountBehavior.php:105;132 +msgid "Account not found for the given token and email." +msgstr "Compte non trouvĆ© pour le jeton et le courriel spĆ©cifiĆ©s" + +#: Model/Behavior/SocialBehavior.php:56 +msgid "Unable to login user with reference {0}" +msgstr "Impossible d'identifier l'utilisateur avec la rĆ©fĆ©rence {0}" + +#: Model/Behavior/SocialBehavior.php:98 +msgid "Email not present" +msgstr "Courriel non prĆ©sent" + +#: Model/Table/UsersTable.php:82 +msgid "Your password does not match your confirm password. Please try again" +msgstr "" +"Votre mot de passe ne correspond pas Ć  la confirmation de mot de passe. " +"Veuillez rĆ©essayer" + +#: Model/Table/UsersTable.php:175 +msgid "Username already exists" +msgstr "Le nom d'utilisateur existe dĆ©jĆ " + +#: Model/Table/UsersTable.php:181 +msgid "Email already exists" +msgstr "Le courriel existe dĆ©jĆ " + +#: Model/Table/UsersTable.php:214 +msgid "Missing 'username' in options data" +msgstr "'username' manquant dans les donnĆ©es d'options" + +#: Shell/UsersShell.php:54 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Utilitaires pour le Plugin CakeDC Users" + +#: Shell/UsersShell.php:55 +msgid "Activate an specific user" +msgstr "Activer un utilisateur spĆ©cifique" + +#: Shell/UsersShell.php:56 +msgid "Add a new superadmin user for testing purposes" +msgstr "" +"Ajouter un nouvel utilisateur super-administrateur pour des besoins de tests" + +#: Shell/UsersShell.php:57 +msgid "Add a new user" +msgstr "Ajouter un nouvel utilisateur" + +#: Shell/UsersShell.php:58 +msgid "Change the role for an specific user" +msgstr "Changer le rĆ“le d'un utilisateur spĆ©cifique" + +#: Shell/UsersShell.php:59 +msgid "Deactivate an specific user" +msgstr "DĆ©sactiver un utilisateur spĆ©cifique" + +#: Shell/UsersShell.php:60 +msgid "Delete an specific user" +msgstr "Supprimer un utilisateur spĆ©cifique" + +#: Shell/UsersShell.php:61 +msgid "Reset the password via email" +msgstr "RĆ©initialiser le mot de passe par courriel" + +#: Shell/UsersShell.php:62 +msgid "Reset the password for all users" +msgstr "RĆ©initialiser le mot de passe de tous les utilisateurs" + +#: Shell/UsersShell.php:63 +msgid "Reset the password for an specific user" +msgstr "RĆ©initialiser le mot de passe pour un utilisateur spĆ©cifique" + +#: Shell/UsersShell.php:98 +msgid "User added:" +msgstr "Utilisateur ajoutĆ© :" + +#: Shell/UsersShell.php:99;127 +msgid "Id: {0}" +msgstr "Identifiant : {0}" + +#: Shell/UsersShell.php:100;128 +msgid "Username: {0}" +msgstr "Nom d'utilisateur : {0}" + +#: Shell/UsersShell.php:101;129 +msgid "Email: {0}" +msgstr "Courriel : {0}" + +#: Shell/UsersShell.php:102;130 +msgid "Password: {0}" +msgstr "Mot de passe : {0}" + +#: Shell/UsersShell.php:126 +msgid "Superuser added:" +msgstr "Super-utilisateur ajoutĆ© :" + +#: Shell/UsersShell.php:132 +msgid "Superuser could not be added:" +msgstr "Le super-utilisateur n'a pas pu ĆŖtre ajoutĆ© :" + +#: Shell/UsersShell.php:135 +msgid "Field: {0} Error: {1}" +msgstr "Champ : {0} Erreur : {1}" + +#: Shell/UsersShell.php:153;179 +msgid "Please enter a password." +msgstr "Veuillez saisir un mot de passe." + +#: Shell/UsersShell.php:157 +msgid "Password changed for all users" +msgstr "Mot de passe changĆ© pour tous les utilisateurs" + +#: Shell/UsersShell.php:158;186 +msgid "New password: {0}" +msgstr "Nouveau mot de passe : {0}" + +#: Shell/UsersShell.php:176;204;282;324 +msgid "Please enter a username." +msgstr "Veuillez saisir un nom d'utilisateur." + +#: Shell/UsersShell.php:185 +msgid "Password changed for user: {0}" +msgstr "Mot de passe changĆ© pour l'utilisateur : {0}" + +#: Shell/UsersShell.php:207 +msgid "Please enter a role." +msgstr "Veuillez saisir un rĆ“le." + +#: Shell/UsersShell.php:213 +msgid "Role changed for user: {0}" +msgstr "RĆ“le changĆ© pour l'utilisateur : {0}" + +#: Shell/UsersShell.php:214 +msgid "New role: {0}" +msgstr "Nouveau rĆ“le : {0}" + +#: Shell/UsersShell.php:229 +msgid "User was activated: {0}" +msgstr "L'utilisateur a Ć©tĆ© activĆ© : {0}" + +#: Shell/UsersShell.php:244 +msgid "User was de-activated: {0}" +msgstr "L'utilisateur a Ć©tĆ© dĆ©sactivĆ© : {0]" + +#: Shell/UsersShell.php:256 +msgid "Please enter a username or email." +msgstr "Veuillez saisir un nom d'utilisateur ou un courriel." + +#: Shell/UsersShell.php:264 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"Veuillez demander Ć  l'utilisateur de vĆ©rifier ses courriels pour poursuivre " +"la procĆ©dure de rĆ©initialisation du mot de passe." + +#: Shell/UsersShell.php:302 +msgid "The user was not found." +msgstr "L'utilisateur n'a pas Ć©tĆ© trouvĆ©." + +#: Shell/UsersShell.php:332 +msgid "The user {0} was not deleted. Please try again" +msgstr "L'utilisateur {0} n'a pas Ć©tĆ© supprimĆ©. Veuillez rĆ©essayer" + +#: Shell/UsersShell.php:334 +msgid "The user {0} was deleted successfully" +msgstr "L'utilisateur {0} a Ć©tĆ© supprimĆ© avec succĆØs" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Bonjour {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "RĆ©initialisez votre mot de passe ici" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correcly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Si le lien n'est pas correctement affichĆ©, veuillez copier l'adresse " +"suivante dans votre navigateur web {0}" + +#: Template/Email/html/reset_password.ctp:30 +#: Template/Email/html/social_account_validation.ctp:35 +#: Template/Email/html/validation.ctp:30 +#: Template/Email/text/reset_password.ctp:24 +#: Template/Email/text/social_account_validation.ctp:26 +#: Template/Email/text/validation.ctp:24 +msgid "Thank you" +msgstr "Merci" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Activez votre identification sociale ici" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Activez votre compte ici" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Veuillez copier l'adresse suivante dans votre navigateur web {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"Veuillez copier l'adresse suivante dans votre navigateur web pour activer " +"votre identification sociale {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 +msgid "Actions" +msgstr "Actions" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 +#: Template/Users/view.ctp:19 +msgid "List Users" +msgstr "Lister les utilisateurs" + +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:21 +msgid "List Accounts" +msgstr "Lister les comptes" + +#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 +msgid "Add User" +msgstr "Ajouter un utilisateur" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 +#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 +msgid "Username" +msgstr "Nom d'utilisateur" + +#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 +msgid "Email" +msgstr "Courriel" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 +msgid "First name" +msgstr "PrĆ©nom" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 +msgid "Last name" +msgstr "Nom" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:44;75 +msgid "Active" +msgstr "Actif" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Envoyer" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Veuillez entrer le nouveau mot de passe" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Mot de passe actuel" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Nouveau mot de passe" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 +msgid "Confirm password" +msgstr "Confirmer le mot de passe" + +#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:101 +msgid "Delete" +msgstr "Supprimer" + +#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:18;101 +msgid "Are you sure you want to delete # {0}?" +msgstr "Ɗtes vous sĆ»r(e) de vouloir supprimler # {0} ?" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Modifier l'utilisateur" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 +msgid "Token" +msgstr "Jeton" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Expiration du jeton" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "Jeton d'API" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Date d'activiation" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "Date CGU" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Nouveau {0}" + +#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 +msgid "View" +msgstr "Voir" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Changer le mot de passe" + +#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 +msgid "Edit" +msgstr "Modifier" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "prĆ©cĆ©dent" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "suivant" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Merci de saisir votre nom d'utilisateur et votre mot de passe" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "Se souvenir de moi" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "S'inscrire" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "RĆ©initialiser le mot de passe" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "S'identifier" + +#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:24 +msgid "Change Password" +msgstr "Changer le mot de passe" + +#: Template/Users/profile.ctp:34 +msgid "Social Accounts" +msgstr "Comptes sociaux" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 +msgid "Avatar" +msgstr "Photo de profil" + +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 +msgid "Provider" +msgstr "Fournisseur" + +#: Template/Users/profile.ctp:40 +msgid "Link" +msgstr "Lien" + +#: Template/Users/profile.ctp:47 +msgid "Link to {0}" +msgstr "Lier Ć  {0}" + +#: Template/Users/register.ctp:20 +msgid "Password" +msgstr "Mot de passe" + +#: Template/Users/register.ctp:28 +msgid "Accept TOS conditions?" +msgstr "Accepter les CGU ?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Merci de saisir votre email pour rĆ©initialiser votre mot de passe" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "RĆ©envoyer le courriel de validation" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "Courriel ou nom d'utilisateur" + +#: Template/Users/view.ctp:18 +msgid "Delete User" +msgstr "Supprimer l'utilisateur" + +#: Template/Users/view.ctp:20 +msgid "New User" +msgstr "Nouvel utilisateur" + +#: Template/Users/view.ctp:28;67 +msgid "Id" +msgstr "Identifiant" + +#: Template/Users/view.ctp:34 +msgid "First Name" +msgstr "PrĆ©nom" + +#: Template/Users/view.ctp:36 +msgid "Last Name" +msgstr "Nom" + +#: Template/Users/view.ctp:40 +msgid "Api Token" +msgstr "Jeton d'API" + +#: Template/Users/view.ctp:48;74 +msgid "Token Expires" +msgstr "Expiration du jeton" + +#: Template/Users/view.ctp:50 +msgid "Activation Date" +msgstr "Date d'activiation" + +#: Template/Users/view.ctp:52 +msgid "Tos Date" +msgstr "Date CGU" + +#: Template/Users/view.ctp:54;77 +msgid "Created" +msgstr "CrĆ©Ć© le" + +#: Template/Users/view.ctp:56;78 +msgid "Modified" +msgstr "ModifiĆ© le" + +#: Template/Users/view.ctp:63 +msgid "Related Accounts" +msgstr "Comptes liĆ©s" + +#: Template/Users/view.ctp:68 +msgid "User Id" +msgstr "Identifiant utilisateur" + +#: Template/Users/view.ctp:71 +msgid "Reference" +msgstr "RĆ©fĆ©rence" + +#: Template/Users/view.ctp:76 +msgid "Data" +msgstr "DonnĆ©es" + +#: View/Helper/UserHelper.php:46 +msgid "Sign in with" +msgstr "S'identifier avec" + +#: View/Helper/UserHelper.php:49 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:52 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:91 +msgid "Logout" +msgstr "Se dĆ©connecter" + +#: View/Helper/UserHelper.php:108 +msgid "Welcome, {0}" +msgstr "Bienvenue, {0}" + +#: View/Helper/UserHelper.php:131 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"reCaptcha n'est pas configurĆ© ! Veuillez configurer Users.reCaptcha.key" + +#: Model/Behavior/RegisterBehavior.php:148 +msgid "This field is required" +msgstr "Ce champ est requis" + +#~ msgid "The old password does not match" +#~ msgstr "L'ancien mot de passe ne correspond pas" + +#~ msgid "" +#~ "If the link is not correctly displayed, please copy the following address " +#~ "in your web browser {0}" +#~ msgstr "" +#~ "Si le lien n'est pas correctement affichĆ©, veuillez copier l'adresse " +#~ "suivante dans votre navigateur web {0}" diff --git a/src/Locale/hu_HU/Users.mo b/src/Locale/hu_HU/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..ce8e248ce1e47f5ee7993b5aeebfaad260a498ea GIT binary patch literal 14725 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 literal 0 HcmV?d00001 diff --git a/src/Locale/hu_HU/Users.po b/src/Locale/hu_HU/Users.po new file mode 100644 index 000000000..4fb02e3f6 --- /dev/null +++ b/src/Locale/hu_HU/Users.po @@ -0,0 +1,816 @@ +# LANGUAGE translation of CakePHP Application +# Copyright YEAR NAME +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2017-10-23 16:36+0200\n" +"PO-Revision-Date: 2017-10-23 17:17+0200\n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.1\n" +"Last-Translator: rrd \n" +"Language: hu_HU\n" + +#: Auth/SocialAuthenticate.php:456 +msgid "Provider cannot be empty" +msgstr "A kiszolgĆ”lĆ³ nem lehet Ć¼res" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "A fiĆ³k sikeresen ellenőrizve" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "A fiĆ³kot nem tudtam ellenőrizni" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "ƉrvĆ©nytelen token Ć©s/vagy kƶzƶssĆ©gi fiĆ³k" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "A kƶzƶssĆ©gi fiĆ³k mĆ”r aktĆ­v" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "A kƶzƶssĆ©gi fiĆ³k nem ellenőrizhető" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "Az email sikeresen elkĆ¼ldve" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "Az emailt nem tudtuk elkĆ¼ldeni" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "ƉrvĆ©nytelen fiĆ³k" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "Az emailt nem lehet ĆŗjrakĆ¼ldeni" + +#: Controller/Component/RememberMeComponent.php:68 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" +"ƉrvĆ©nytelen alkalamzĆ”s sĆ³. Az alkalmazĆ”s sĆ³nak legalĆ”bb 256 bit (32 byte) " +"hosszĆŗnak kell lennie" + +#: Controller/Component/UsersAuthComponent.php:204 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "Nem tudod engedĆ©lyezni az email ellenőrzĆ©st ha a use_email false" + +#: Controller/Traits/LinkSocialTrait.php:54 +msgid "Could not associate account, please try again." +msgstr "Nem sikerĆ¼lt tĆ”rsĆ­tani a fiĆ³kot, prĆ³bĆ”ld meg mĆ©g egyszer." + +#: Controller/Traits/LinkSocialTrait.php:77 +msgid "Social account was associated." +msgstr "A kƶzƶssĆ©gi fiĆ³k tĆ”rsĆ­tva." + +#: Controller/Traits/LoginTrait.php:104 +msgid "Issues trying to log in with your social account" +msgstr "Gond van a kƶzƶssĆ©gi fiĆ³kkal valĆ³ belĆ©pĆ©ssel." + +#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Add meg az emailedet." + +#: Controller/Traits/LoginTrait.php:120 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"A felhasznĆ”lĆ³d mĆ©g nincs ellenőrizve. NĆ”zd meg az emailjeidet a teendőkĆ©rt." + +#: Controller/Traits/LoginTrait.php:125 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"A kƶzƶssĆ©gi fiĆ³kod mĆ©g nincs ellenőrizve. NĆ”zd meg az emailjeidet a " +"teendőkĆ©rt." + +#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 +msgid "Invalid reCaptcha" +msgstr "ƉrvĆ©nytelen reCaptcha" + +#: Controller/Traits/LoginTrait.php:191 +msgid "You are already logged in" +msgstr "MĆ”r be vagy jelentkezve" + +#: Controller/Traits/LoginTrait.php:212 +msgid "Please enable Google Authenticator first." +msgstr "Előszƶr engedĆ©lyezd a Google Authenticatort." + +#: Controller/Traits/LoginTrait.php:287 +msgid "Verification code is invalid. Try again" +msgstr "Az ellenőrző kĆ³d Ć©rvĆ©nytelen. PrĆ³bĆ”ld meg Ćŗjra" + +#: Controller/Traits/LoginTrait.php:340 +msgid "Username or password is incorrect" +msgstr "A felhasznĆ”lĆ³i nĆ©v vagy a jelszĆ³ helytelen" + +#: Controller/Traits/LoginTrait.php:363 +msgid "You've successfully logged out" +msgstr "Sikeresen kijelentkeztĆ©l" + +#: Controller/Traits/PasswordManagementTrait.php:49;82 +#: Controller/Traits/ProfileTrait.php:50 +msgid "User was not found" +msgstr "A felhasznĆ”lĆ³ nem talĆ”lhatĆ³" + +#: Controller/Traits/PasswordManagementTrait.php:70;78;86 +msgid "Password could not be changed" +msgstr "A jelszĆ³t nem tudtuk mĆ³dosĆ­tani" + +#: Controller/Traits/PasswordManagementTrait.php:74 +msgid "Password has been changed successfully" +msgstr "A jelszĆ³ siekresen mĆ³dosĆ­tva" + +#: Controller/Traits/PasswordManagementTrait.php:84 +msgid "{0}" +msgstr "" + +#: Controller/Traits/PasswordManagementTrait.php:127 +msgid "Please check your email to continue with password reset process" +msgstr "NĆ©zd meg az emailjeidet a jelszĆ³ visszaĆ”llĆ­tĆ”s folytatĆ”sĆ”hoz" + +#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 +msgid "The password token could not be generated. Please try again" +msgstr "A jelszĆ³ token lĆ©trehozĆ”sa sikertelen. PrĆ³bĆ”ld meg Ćŗjra" + +#: Controller/Traits/PasswordManagementTrait.php:136 +#: Controller/Traits/UserValidationTrait.php:107 +msgid "User {0} was not found" +msgstr "A {0} felhasznĆ”lĆ³ nem talĆ”lhatĆ³" + +#: Controller/Traits/PasswordManagementTrait.php:138 +msgid "The user is not active" +msgstr "A felhasznĆ”lĆ³ nem aktĆ­v" + +#: Controller/Traits/PasswordManagementTrait.php:140 +#: Controller/Traits/UserValidationTrait.php:102;111 +msgid "Token could not be reset" +msgstr "A token nem Ć”llĆ­thatĆ³ vissza" + +#: Controller/Traits/PasswordManagementTrait.php:164 +msgid "Google Authenticator token was successfully reset" +msgstr "A Google Authenticator token sikeresen visszaĆ”llĆ­tva" + +#: Controller/Traits/ProfileTrait.php:54 +msgid "Not authorized, please login first" +msgstr "MĆ©g nem jelentkeztĆ©l be. Jelentkezz be" + +#: Controller/Traits/RegisterTrait.php:43 +msgid "You must log out to register a new user account" +msgstr "Ki kell lĆ©pned ahhoz, hogy Ćŗj fiĆ³kot tudj lĆ©trehozni" + +#: Controller/Traits/RegisterTrait.php:89 +msgid "The user could not be saved" +msgstr "A felhasznĆ”lĆ³t nem lehet menteni" + +#: Controller/Traits/RegisterTrait.php:123 +msgid "You have registered successfully, please log in" +msgstr "Sikeresen regisztrĆ”ltĆ”l, lĆ©pj be" + +#: Controller/Traits/RegisterTrait.php:125 +msgid "Please validate your account before log in" +msgstr "KĆ©rlek jitelesĆ­tsd a fiĆ³kodat mielőtt belĆ©pnĆ©l" + +#: Controller/Traits/SimpleCrudTrait.php:77;107 +msgid "The {0} has been saved" +msgstr "A {0} mentve" + +#: Controller/Traits/SimpleCrudTrait.php:81;111 +msgid "The {0} could not be saved" +msgstr "A {0} nincs mentve" + +#: Controller/Traits/SimpleCrudTrait.php:131 +msgid "The {0} has been deleted" +msgstr "A {0} tƶrƶlve" + +#: Controller/Traits/SimpleCrudTrait.php:133 +msgid "The {0} could not be deleted" +msgstr "A {0} nem lett tƶrƶlve" + +#: Controller/Traits/SocialTrait.php:40 +msgid "The reCaptcha could not be validated" +msgstr "A reCaptcha nem ellenőrizhető" + +#: Controller/Traits/UserValidationTrait.php:43 +msgid "User account validated successfully" +msgstr "A fiĆ³k sikeresen ellenőrizve" + +#: Controller/Traits/UserValidationTrait.php:45 +msgid "User account could not be validated" +msgstr "A fiĆ³kot nem sikerĆ¼lt ellnőrizni" + +#: Controller/Traits/UserValidationTrait.php:48 +msgid "User already active" +msgstr "A fiĆ³k mĆ”r aktĆ­v" + +#: Controller/Traits/UserValidationTrait.php:54 +msgid "Reset password token was validated successfully" +msgstr "A jelszĆ³ helyreĆ”llĆ­tĆ³ token sikeresen ellenőrizve" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Reset password token could not be validated" +msgstr "A jelszĆ³ helyreĆ”llĆ­tĆ³ token ellenőrzĆ©se sikertelen" + +#: Controller/Traits/UserValidationTrait.php:66 +msgid "Invalid validation type" +msgstr "Helytelen ellenőrzĆ©s tĆ­pus" + +#: Controller/Traits/UserValidationTrait.php:69 +msgid "Invalid token or user account already validated" +msgstr "Helytelen token vagy a fiĆ³k mĆ”r ellenőrizve van" + +#: Controller/Traits/UserValidationTrait.php:71 +msgid "Token already expired" +msgstr "A token mĆ”r lejĆ”rt" + +#: Controller/Traits/UserValidationTrait.php:97 +msgid "Token has been reset successfully. Please check your email." +msgstr "A token helyreĆ”llĆ­tva. NĆ©zd meg az emailjeidet." + +#: Controller/Traits/UserValidationTrait.php:109 +msgid "User {0} is already active" +msgstr "{0} felhasznĆ”lĆ³ mĆ”r aktĆ­v" + +#: Mailer/UsersMailer.php:34 +msgid "Your account validation link" +msgstr "A fiĆ³kod hitelesĆ­tĆ©si linkje" + +#: Mailer/UsersMailer.php:52 +msgid "{0}Your reset password link" +msgstr "{0} A jelszĆ³ helyreĆ”llĆ­tĆ”s linkje" + +#: Mailer/UsersMailer.php:75 +msgid "{0}Your social account validation link" +msgstr "{0} A kƶzƶssĆ©gi fiĆ³kod ellenőrzĆ©si linkje" + +#: Model/Behavior/AuthFinderBehavior.php:49 +msgid "Missing 'username' in options data" +msgstr "HiĆ”nyzĆ³ 'username' az opciĆ³kban" + +#: Model/Behavior/LinkSocialBehavior.php:53 +msgid "Social account already associated to another user" +msgstr "A kƶzƶssĆ©gi fiĆ³k mĆ”r csatlakoztatva van egy mĆ”sik felhasznĆ”lĆ³hoz" + +#: Model/Behavior/PasswordBehavior.php:45 +msgid "Reference cannot be null" +msgstr "A hivatkozĆ”s nem lehet null" + +#: Model/Behavior/PasswordBehavior.php:50 +msgid "Token expiration cannot be empty" +msgstr "A token lejĆ”rat nme lehet Ć¼res" + +#: Model/Behavior/PasswordBehavior.php:56;117 +msgid "User not found" +msgstr "A felhasznĆ”lĆ³ nem talĆ”lhatĆ³" + +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112;205 +msgid "User account already validated" +msgstr "A felhasznĆ”lĆ³i fiĆ³k mĆ”r ellenőrizve van" + +#: Model/Behavior/PasswordBehavior.php:67 +msgid "User not active" +msgstr "A felhasznĆ”lĆ³ nem aktĆ­v" + +#: Model/Behavior/PasswordBehavior.php:122 +msgid "The current password does not match" +msgstr "A jelenlegi jelszĆ³ nem stimmel" + +#: Model/Behavior/PasswordBehavior.php:125 +msgid "You cannot use the current password as the new one" +msgstr "Nem lehet az Ćŗj jelszĆ³ azonos a rĆ©givel" + +#: Model/Behavior/RegisterBehavior.php:90 +msgid "User not found for the given token and email." +msgstr "Nem talĆ”lhatĆ³ felhasznĆ”lĆ³ ehhez a tokenhez Ć©s emailhez." + +#: Model/Behavior/RegisterBehavior.php:93 +msgid "Token has already expired user with no token" +msgstr "A token lejĆ”rt felhasznĆ”lĆ³ token nĆ©lkĆ¼l" + +#: Model/Behavior/SocialAccountBehavior.php:103;130 +msgid "Account already validated" +msgstr "A fiĆ³k mĆ”r ellenőrizve van" + +#: Model/Behavior/SocialAccountBehavior.php:106;133 +msgid "Account not found for the given token and email." +msgstr "Nem talĆ”lhatĆ³ fiĆ³k ehhez a tokenhez Ć©s emailhez." + +#: Model/Behavior/SocialBehavior.php:82 +msgid "Unable to login user with reference {0}" +msgstr "Nem tudom belĆ©pni a usert a {0} hivatkozĆ”ssal" + +#: Model/Behavior/SocialBehavior.php:121 +msgid "Email not present" +msgstr "HiĆ”nyzĆ³ email" + +#: Model/Table/UsersTable.php:81 +msgid "Your password does not match your confirm password. Please try again" +msgstr "A jelszavad Ć©s a jelszĆ³ megerősĆ­tĆ©s nem azonos. PrĆ³bĆ”ld meg Ćŗjra" + +#: Model/Table/UsersTable.php:173 +msgid "Username already exists" +msgstr "A felhasznĆ”lĆ³nĆ©v mĆ”r foglalt" + +#: Model/Table/UsersTable.php:179 +msgid "Email already exists" +msgstr "Az email mĆ”r foglalt" + +#: Shell/UsersShell.php:58 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Eszkƶzƶk a CakeDC Users Puginhez" + +#: Shell/UsersShell.php:60 +msgid "Activate an specific user" +msgstr "Egy bizonyos felhasznĆ”lĆ³ aktivĆ”lĆ”sa" + +#: Shell/UsersShell.php:63 +msgid "Add a new superadmin user for testing purposes" +msgstr "ƚj superadmin hozzĆ”adĆ”sa tesztelĆ©si cĆ©llal" + +#: Shell/UsersShell.php:66 +msgid "Add a new user" +msgstr "ƚj felhasznĆ”lĆ³" + +#: Shell/UsersShell.php:69 +msgid "Change the role for an specific user" +msgstr "Egy felhasznĆ”lĆ³i szerep mĆ³dosĆ­tĆ”sa" + +#: Shell/UsersShell.php:72 +msgid "Deactivate an specific user" +msgstr "Egy felhasznĆ”lĆ³ deaktivĆ”lĆ”sa" + +#: Shell/UsersShell.php:75 +msgid "Delete an specific user" +msgstr "Egy felhasznĆ”lĆ³ tƶrlĆ©se" + +#: Shell/UsersShell.php:78 +msgid "Reset the password via email" +msgstr "JelszĆ³ helyreĆ”llĆ­tĆ”s emailben" + +#: Shell/UsersShell.php:81 +msgid "Reset the password for all users" +msgstr "Minden feĆ©hasznĆ”lĆ³ jelszavĆ”nak visszaĆ”llĆ­tĆ”sa" + +#: Shell/UsersShell.php:84 +msgid "Reset the password for an specific user" +msgstr "Egy felhasznĆ”lĆ³ jelszavĆ”nak visszaĆ”llĆ­tĆ”sa" + +#: Shell/UsersShell.php:133;159 +msgid "Please enter a password." +msgstr "Adj meg egy jelszĆ³t" + +#: Shell/UsersShell.php:137 +msgid "Password changed for all users" +msgstr "Mindne felhasznĆ”lĆ³ jelszava mĆ³dosĆ­tva" + +#: Shell/UsersShell.php:138;166 +msgid "New password: {0}" +msgstr "ƚj jelszĆ³: {0}" + +#: Shell/UsersShell.php:156;184;262;359 +msgid "Please enter a username." +msgstr "Adj meg egy felhasznĆ”lĆ³nevet." + +#: Shell/UsersShell.php:165 +msgid "Password changed for user: {0}" +msgstr "A {0} felhasznĆ”lĆ³ jelszava megvĆ”ltoztatva" + +#: Shell/UsersShell.php:187 +msgid "Please enter a role." +msgstr "Adj meg egy szerepet." + +#: Shell/UsersShell.php:193 +msgid "Role changed for user: {0}" +msgstr "{0} felhasznĆ”lĆ³ szerepe mĆ³dosĆ­tva" + +#: Shell/UsersShell.php:194 +msgid "New role: {0}" +msgstr "ƚj szerep: {0}" + +#: Shell/UsersShell.php:209 +msgid "User was activated: {0}" +msgstr "{0} felhasznĆ”lĆ³ aktivĆ”lva" + +#: Shell/UsersShell.php:224 +msgid "User was de-activated: {0}" +msgstr "{0} felhasznĆ”lĆ³ deaktivĆ”lva" + +#: Shell/UsersShell.php:236 +msgid "Please enter a username or email." +msgstr "Adj meg egy felhasznĆ”lĆ³nevet vagy egy emailt." + +#: Shell/UsersShell.php:244 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"KĆ©rd meg a felhasznĆ”lĆ³t, hogy nĆ©zze meg az emailjeit, hogy folytatni tudja a " +"jelszĆ³ visszaĆ”llĆ­tĆ”si folyamatot" + +#: Shell/UsersShell.php:308 +msgid "Superuser added:" +msgstr "Superuser hozzĆ”adva:" + +#: Shell/UsersShell.php:310 +msgid "User added:" +msgstr "A felhasznĆ”lĆ³ hozzĆ”adva:" + +#: Shell/UsersShell.php:312 +msgid "Id: {0}" +msgstr "" + +#: Shell/UsersShell.php:313 +msgid "Username: {0}" +msgstr "FelhasznĆ”lĆ³nĆ©v: {0}" + +#: Shell/UsersShell.php:314 +msgid "Email: {0}" +msgstr "" + +#: Shell/UsersShell.php:315 +msgid "Role: {0}" +msgstr "Szerep: {0}" + +#: Shell/UsersShell.php:316 +msgid "Password: {0}" +msgstr "JelszĆ³: {0}" + +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "A felhasznĆ”lĆ³t ne tudtuk hozzĆ”adni:" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" +msgstr "Mező: {0} Hiba: {1}" + +#: Shell/UsersShell.php:337 +msgid "The user was not found." +msgstr "A felhasznĆ”lĆ³ nem talĆ”lhatĆ³" + +#: Shell/UsersShell.php:367 +msgid "The user {0} was not deleted. Please try again" +msgstr "{0} felhasznĆ”lĆ³ nem lett tƶrƶlve. PrĆ³bĆ”ld meg Ćŗjra" + +#: Shell/UsersShell.php:369 +msgid "The user {0} was deleted successfully" +msgstr "{0} felhasznĆ”lĆ³ sikeresen tƶrƶlve" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Szia {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "JelszĆ³ visszaĆ”llĆ­tĆ”s" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Ha a link nem jelenik meg jĆ³l, akkor mĆ”sold be ezt a cĆ­met a bƶngĆ©sződbe {0}" + +#: Template/Email/html/reset_password.ctp:34 +#: Template/Email/html/social_account_validation.ctp:39 +#: Template/Email/html/validation.ctp:34 +#: Template/Email/text/reset_password.ctp:28 +#: Template/Email/text/social_account_validation.ctp:30 +#: Template/Email/text/validation.ctp:28 +msgid "Thank you" +msgstr "Kƶszi" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "AktivĆ”ld a kƶzƶssĆ©gi fiĆ³kodat" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "AktivĆ”ld a fiĆ³kodat" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "MĆ”sold be a bƶngĆ©sződbe ezt a cĆ­met {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"MĆ”sold be a bƶngĆ©sződbe ezt a cĆ­met a kƶzƶssĆ©gi fiĆ³kod aktivĆ”lĆ”sĆ”hoz {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 +msgid "Actions" +msgstr "Műveletek" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:23 +msgid "List Users" +msgstr "FelhasznĆ”lĆ³k" + +#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 +msgid "Add User" +msgstr "ƚj felhasznĆ”lĆ³" + +#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 +msgid "Username" +msgstr "FelhasznĆ”lĆ³i nĆ©v" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 +msgid "Email" +msgstr "" + +#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 +msgid "Password" +msgstr "JelszĆ³" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 +msgid "First name" +msgstr "KeresztnĆ©v" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 +msgid "Last name" +msgstr "CsalĆ”di nĆ©v" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:49;74 +msgid "Active" +msgstr "AktĆ­v" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Ment" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Add meg az Ćŗj jelszĆ³t" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Jelenlegi jelszĆ³" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "ƚj jelszĆ³" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 +msgid "Confirm password" +msgstr "JelszĆ³ megerősĆ­tĆ©se" + +#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 +msgid "Delete" +msgstr "TƶrlĆ©s" + +#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:21 +msgid "Are you sure you want to delete # {0}?" +msgstr "Biztos tƶrlƶd # {0}?" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "FelhasznĆ”lĆ³ mĆ³dosĆ­tĆ”sa" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 +msgid "Token" +msgstr "" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Token lejĆ”rat" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "AktivĆ”lĆ”s dĆ”tuma" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "FelhasznĆ”lĆ³ feltĆ©telek dĆ”tuma" + +#: Template/Users/edit.ctp:63 +msgid "Reset Google Authenticator Token" +msgstr "Google Authenticator Token visszaĆ”llĆ­tĆ”sa" + +#: Template/Users/edit.ctp:69 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "" +"Biztos vagy benne, hogy vissza akarod Ć”llĆ­tani {0} felhasznĆ”lĆ³ tokenjĆ©t?" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "ƚj {0}" + +#: Template/Users/index.ctp:37 +msgid "View" +msgstr "Mutat" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "JElszĆ³ mĆ³dosĆ­tĆ”s" + +#: Template/Users/index.ctp:39 +msgid "Edit" +msgstr "Szerkeszt" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "előző" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "kƶvetkező" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Add meg a felhasznĆ”lĆ³i nevedet Ć©s a jelszavadat" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "EmlĆ©kezz rĆ”m" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "RegisztrĆ”lok" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "JelszĆ³ visszaĆ”llĆ­tĆ”s" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "BelĆ©pĆ©s" + +#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 +msgid "{0} {1}" +msgstr "" + +#: Template/Users/profile.ctp:27 +msgid "Change Password" +msgstr "JelszĆ³ mĆ³dosĆ­tĆ”s" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 +msgid "Social Accounts" +msgstr "KƶzƶssĆ©gi fiĆ³kok" + +#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 +msgid "Avatar" +msgstr "" + +#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 +msgid "Provider" +msgstr "KiszolgĆ”lĆ³" + +#: Template/Users/profile.ctp:44 +msgid "Link" +msgstr "" + +#: Template/Users/profile.ctp:51 +msgid "Link to {0}" +msgstr "KapcsolĆ³dva: {0}" + +#: Template/Users/register.ctp:29 +msgid "Accept TOS conditions?" +msgstr "Elfogadod a felhasznĆ”lĆ³ feltĆ©teleket?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Add meg az emailcĆ­medet a jelszĆ³ helyreĆ”llĆ­tĆ”shoz" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Ellenƶrző email ĆŗjrakĆ¼ldĆ©se" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "Email vagy felhasznĆ”lĆ³ nĆ©v" + +#: Template/Users/verify.ctp:13 +msgid "Verification Code" +msgstr "Ellenƶrző kĆ³d" + +#: Template/Users/verify.ctp:15 +msgid "" +" " +"Verify" +msgstr "" +" " +"Ellenőriz" + +#: Template/Users/view.ctp:19 +msgid "Delete User" +msgstr "FelhasznĆ”lĆ³ tƶrlĆ©se" + +#: Template/Users/view.ctp:24 +msgid "New User" +msgstr "ƚj felhasznĆ”lĆ³" + +#: Template/Users/view.ctp:31 +msgid "Id" +msgstr "" + +#: Template/Users/view.ctp:37 +msgid "First Name" +msgstr "KeresztnĆ©v" + +#: Template/Users/view.ctp:39 +msgid "Last Name" +msgstr "CsalĆ”di nĆ©v" + +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "Szerep" + +#: Template/Users/view.ctp:45 +msgid "Api Token" +msgstr "" + +#: Template/Users/view.ctp:53 +msgid "Token Expires" +msgstr "Token lejĆ”rat" + +#: Template/Users/view.ctp:55 +msgid "Activation Date" +msgstr "AktivĆ”lĆ”s dĆ”tuma" + +#: Template/Users/view.ctp:57 +msgid "Tos Date" +msgstr "FelhasznĆ”lĆ³i feltĆ©telek dĆ”tuma" + +#: Template/Users/view.ctp:59;75 +msgid "Created" +msgstr "LĆ©trehozva" + +#: Template/Users/view.ctp:61;76 +msgid "Modified" +msgstr "MĆ³dosĆ­tva" + +#: View/Helper/UserHelper.php:45 +msgid "Sign in with" +msgstr "BelĆ©pĆ©s ezzel" + +#: View/Helper/UserHelper.php:48 +msgid "fa fa-{0}" +msgstr "" + +#: View/Helper/UserHelper.php:57 +msgid "btn btn-social btn-{0} " +msgstr "" + +#: View/Helper/UserHelper.php:106 +msgid "Logout" +msgstr "KilĆ©p" + +#: View/Helper/UserHelper.php:123 +msgid "Welcome, {0}" +msgstr "Ɯdv {0}!" + +#: View/Helper/UserHelper.php:146 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"A reCaptcha nincs beĆ”llĆ­tva! Ellenőrizd a Users.reCaptcha.key beĆ”llĆ­tĆ”st" + +#: View/Helper/UserHelper.php:205 +msgid "btn btn-social btn-{0}" +msgstr "" + +#: View/Helper/UserHelper.php:211 +msgid "Connected with {0}" +msgstr "ƖsszekapcsolĆ³dva ezzel: {0}" + +#: View/Helper/UserHelper.php:216 +msgid "Connect with {0}" +msgstr "KapcsolĆ³dĆ”s ehhez: {0} " diff --git a/src/Locale/it_IT/Users.mo b/src/Locale/it_IT/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..f242989f460433ffb9e21dea5b545ccbdf20e4d9 GIT binary patch literal 15385 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 literal 0 HcmV?d00001 diff --git a/src/Locale/it_IT/Users.po b/src/Locale/it_IT/Users.po new file mode 100644 index 000000000..80176186a --- /dev/null +++ b/src/Locale/it_IT/Users.po @@ -0,0 +1,783 @@ +# LANGUAGE translation of CakePHP Application +# Copyright 2010 - 2016, Cake Development Corporation (http://cakedc.com) +# +msgid "" +msgstr "" +"Project-Id-Version: CakeDC Users\n" +"POT-Creation-Date: 2017-12-21 12:01+0100\n" +"PO-Revision-Date: 2018-01-12 17:06+0100\n" +"Last-Translator: Silvia Ghignone \n" +"Language-Team: CakeDC \n" +"Language: it_IT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 2.0.5\n" + +#: Auth/ApiKeyAuthenticate.php:73 +msgid "Type {0} is not valid" +msgstr "Il tipo {0} non ĆØ valido" + +#: Auth/ApiKeyAuthenticate.php:77 +msgid "Type {0} has no associated callable" +msgstr "Il tipo {0} non ha nessuna funzione di chiamata associabile" + +#: Auth/ApiKeyAuthenticate.php:86 +msgid "SSL is required for ApiKey Authentication" +msgstr "SSL ĆØ richiesto per ApiKey Authentication" + +#: Auth/SimpleRbacAuthorize.php:142 +msgid "Missing configuration file: \"config/{0}.php\". Using default permissions" +msgstr "File di configurazione mancante: \"config/{0}.php\". Utilizzo dei permessi di default" + +#: Auth/SocialAuthenticate.php:432 +msgid "Provider cannot be empty" +msgstr "Il campo Provider non puĆ² essere vuoto" + +#: Auth/Rules/AbstractRule.php:78 +msgid "" +"Table alias is empty, please define a table alias, we could not extract a default table from the " +"request" +msgstr "" +"L'alias della tabella ĆØ vuoto, per favore definire un alias tabella, non potremmo estrarre una tabella " +"di default dalla richiesta" + +#: Auth/Rules/Owner.php:67;70 +msgid "Missing column {0} in table {1} while checking ownership permissions for user {2}" +msgstr "" +"Colonna {0} mancante nella tabella {1} durante la verifica dei \"\"permessi di proprietĆ  per l'utente " +"{2}" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Account convalidato con successo" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "Non ĆØ stato possibile convalidare l'account" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Token e/o account social non valido" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "Account Social giĆ  attivo" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "Non ĆØ stato possibile convalidare l'Account Social" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "Email inviata con successo" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "Impossibile inviare l'email" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "Account non valido" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "Non ĆØ stato possibile reinviare l'email" + +#: Controller/Component/RememberMeComponent.php:69 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "App salt non valido. App salt deve essere almeno lungo 256 bits (32 bytes)" + +#: Controller/Component/UsersAuthComponent.php:178 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "Non ĆØ possibile abilitare il workflow di validazione email se use_email ĆØ false" + +#: Controller/Traits/LoginTrait.php:96 +msgid "Issues trying to log in with your social account" +msgstr "Si sono verificati dei problemi nel tentativo di effettuare il log in col tuo account social" + +#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Per favore inseirsci la tua email" + +#: Controller/Traits/LoginTrait.php:108 +msgid "Your user has not been validated yet. Please check your inbox for instructions" +msgstr "" +"Il vostro utente non ĆØ ancora stato convalidato. Per favore verifica le tue email in arrivoper " +"ottenere le istruzioni" + +#: Controller/Traits/LoginTrait.php:110 +msgid "Your social account has not been validated yet. Please check your inbox for instructions" +msgstr "" +"Il tuo account social non ĆØ stato ancora convalidato. Per favore verifica la tuacasella di posta " +"elettronica per maggiori informazioni" + +#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 +msgid "Invalid reCaptcha" +msgstr "reCaptcha non valida" + +#: Controller/Traits/LoginTrait.php:171 +msgid "You are already logged in" +msgstr "E' giĆ Ā  stato effettuato il log in" + +#: Controller/Traits/LoginTrait.php:217 +msgid "Username or password is incorrect" +msgstr "Username o password non corretti" + +#: Controller/Traits/LoginTrait.php:238 +msgid "You've successfully logged out" +msgstr "Log out effettuato con successo" + +#: Controller/Traits/PasswordManagementTrait.php:47;76 Controller/Traits/ProfileTrait.php:49 +msgid "User was not found" +msgstr "Utente non trovato" + +#: Controller/Traits/PasswordManagementTrait.php:64;72;80 +msgid "Password could not be changed" +msgstr "Non ĆØ stato possibile cambiare la password" + +#: Controller/Traits/PasswordManagementTrait.php:68 +msgid "Password has been changed successfully" +msgstr "Password modificata con successo" + +#: Controller/Traits/PasswordManagementTrait.php:78 +msgid "{0}" +msgstr "{0}" + +#: Controller/Traits/PasswordManagementTrait.php:120 +msgid "Please check your email to continue with password reset process" +msgstr "Controllare la propria email per continuare col processo di ripristino della password" + +#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 +msgid "The password token could not be generated. Please try again" +msgstr "Non ĆØ stato possibile generare il token della password. Per favore riprovare" + +#: Controller/Traits/PasswordManagementTrait.php:129 Controller/Traits/UserValidationTrait.php:100 +msgid "User {0} was not found" +msgstr "Utente {0} non trovato" + +#: Controller/Traits/PasswordManagementTrait.php:131 +msgid "The user is not active" +msgstr "Utente non attivo" + +#: Controller/Traits/PasswordManagementTrait.php:133 Controller/Traits/UserValidationTrait.php:95;104 +msgid "Token could not be reset" +msgstr "Non ĆØ stato possibile ripristinare il token" + +#: Controller/Traits/ProfileTrait.php:53 +msgid "Not authorized, please login first" +msgstr "Non autorizzato, per favore effettuare prima il login" + +#: Controller/Traits/RegisterTrait.php:42 +msgid "You must log out to register a new user account" +msgstr "Per registrare un nuovo account utente, effettuare prima il log out" + +#: Controller/Traits/RegisterTrait.php:88 +msgid "The user could not be saved" +msgstr "Registrazione utente non riuscita" + +#: Controller/Traits/RegisterTrait.php:122 +msgid "You have registered successfully, please log in" +msgstr "Registrazione avvenuta con successo, per favore effettuare il log in" + +#: Controller/Traits/RegisterTrait.php:124 +msgid "Please validate your account before log in" +msgstr "Per favore convalida il tuo account prima di effettuare il log in" + +#: Controller/Traits/SimpleCrudTrait.php:76;106 +msgid "The {0} has been saved" +msgstr "{0} ĆØ stato salvato" + +#: Controller/Traits/SimpleCrudTrait.php:80;110 +msgid "The {0} could not be saved" +msgstr "Non ĆØ stato possibile salvare {0}" + +#: Controller/Traits/SimpleCrudTrait.php:130 +msgid "The {0} has been deleted" +msgstr "{0} ĆØ stato cancellato" + +#: Controller/Traits/SimpleCrudTrait.php:132 +msgid "The {0} could not be deleted" +msgstr "Non ĆØ stato possibile cancellare {0}" + +#: Controller/Traits/SocialTrait.php:39 +msgid "The reCaptcha could not be validated" +msgstr "Non ĆØ stato possibile convalidare la reCaptcha" + +#: Controller/Traits/UserValidationTrait.php:42 +msgid "User account validated successfully" +msgstr "Account utente convalidato con successo" + +#: Controller/Traits/UserValidationTrait.php:44 +msgid "User account could not be validated" +msgstr "Non ĆØ stato possibile convalidare l'account utente" + +#: Controller/Traits/UserValidationTrait.php:47 +msgid "User already active" +msgstr "Utente giĆ  attivo" + +#: Controller/Traits/UserValidationTrait.php:53 +msgid "Reset password token was validated successfully" +msgstr "Il token per il ripristino password ĆØ stato convalidato con successo" + +#: Controller/Traits/UserValidationTrait.php:58 +msgid "Reset password token could not be validated" +msgstr "Non ĆØ stato possibile convalidare il token per il ripristino della password" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Invalid validation type" +msgstr "Tipo di validazione non valido" + +#: Controller/Traits/UserValidationTrait.php:65 +msgid "Invalid token or user account already validated" +msgstr "Toke non valido o account utente giĆ  convalidato" + +#: Controller/Traits/UserValidationTrait.php:67 +msgid "Token already expired" +msgstr "Token giĆ  scaduto" + +#: Controller/Traits/UserValidationTrait.php:93 +msgid "Token has been reset successfully. Please check your email." +msgstr "Il token ĆØ stato ripristinato con successo. Per favore verificare la propria email." + +#: Controller/Traits/UserValidationTrait.php:102 +msgid "User {0} is already active" +msgstr "L'Utente {0} ĆØ giĆ  attivo" + +#: Email/EmailSender.php:39 +msgid "Your account validation link" +msgstr "Il tuo link per convalidare l'account" + +#: Mailer/UsersMailer.php:55 +msgid "{0}Your reset password link" +msgstr "{0}Ecco il tuo link per ripristinare la password" + +#: Mailer/UsersMailer.php:78 +msgid "{0}Your social account validation link" +msgstr "{0}Ecco il tuo link per convalidare il tuo account social" + +#: Model/Behavior/PasswordBehavior.php:56 +msgid "Reference cannot be null" +msgstr "La referenza non puĆ² essere nulla" + +#: Model/Behavior/PasswordBehavior.php:61 +msgid "Token expiration cannot be empty" +msgstr "La scadenza del Token non puĆ² essere vuota" + +#: Model/Behavior/PasswordBehavior.php:67;116 +msgid "User not found" +msgstr "Utente non trovato" + +#: Model/Behavior/PasswordBehavior.php:71 Model/Behavior/RegisterBehavior.php:111 +msgid "User account already validated" +msgstr "Account utente giĆ  convalidato" + +#: Model/Behavior/PasswordBehavior.php:78 +msgid "User not active" +msgstr "Utente non attivo" + +#: Model/Behavior/PasswordBehavior.php:121 +msgid "The current password does not match" +msgstr "L'attuale password non corrisponde" + +#: Model/Behavior/PasswordBehavior.php:124 +msgid "You cannot use the current password as the new one" +msgstr "Non puoi utilizzare la password attuale come nuova password" + +#: Model/Behavior/RegisterBehavior.php:89 +msgid "User not found for the given token and email." +msgstr "Utente non trovato per l'email ed il token forniti." + +#: Model/Behavior/RegisterBehavior.php:92 +msgid "Token has already expired user with no token" +msgstr "Il token ĆØ giĆ  scaduto utente senza token" + +#: Model/Behavior/SocialAccountBehavior.php:102;129 +msgid "Account already validated" +msgstr "Account giĆ  convalidato" + +#: Model/Behavior/SocialAccountBehavior.php:105;132 +msgid "Account not found for the given token and email." +msgstr "Account non trovato per l'email ed il token forniti." + +#: Model/Behavior/SocialBehavior.php:56 +msgid "Unable to login user with reference {0}" +msgstr "Impossibile effettuare il login per l'utente con referenza {0}" + +#: Model/Behavior/SocialBehavior.php:98 +msgid "Email not present" +msgstr "Email non presente" + +#: Model/Table/UsersTable.php:82 +msgid "Your password does not match your confirm password. Please try again" +msgstr "La password non corrisponde con quella inserita nella conferma password.Per favore riprova" + +#: Model/Table/UsersTable.php:175 +msgid "Username already exists" +msgstr "Username giĆ  esistente" + +#: Model/Table/UsersTable.php:181 +msgid "Email already exists" +msgstr "Email giĆ  esistente" + +#: Model/Table/UsersTable.php:214 +msgid "Missing 'username' in options data" +msgstr "'username' mancante nelle opzioni dati" + +#: Shell/UsersShell.php:54 +msgid "Utilities for CakeDC Users Plugin" +msgstr "UtilitĆ  per Plugin CakeDC Users" + +#: Shell/UsersShell.php:55 +msgid "Activate an specific user" +msgstr "Attiva un utente specifico" + +#: Shell/UsersShell.php:56 +msgid "Add a new superadmin user for testing purposes" +msgstr "Aggiunge un nuovo superadmin per scopi di test" + +#: Shell/UsersShell.php:57 +msgid "Add a new user" +msgstr "Aggiungi un nuovo utente" + +#: Shell/UsersShell.php:58 +msgid "Change the role for an specific user" +msgstr "Cambia il ruolo per un utente specifico" + +#: Shell/UsersShell.php:59 +msgid "Deactivate an specific user" +msgstr "Disattiva un utente specifico" + +#: Shell/UsersShell.php:60 +msgid "Delete an specific user" +msgstr "Cancella un utente specifico" + +#: Shell/UsersShell.php:61 +msgid "Reset the password via email" +msgstr "Ripristina la password per email" + +#: Shell/UsersShell.php:62 +msgid "Reset the password for all users" +msgstr "Ripristina la password per tutti gli utenti" + +#: Shell/UsersShell.php:63 +msgid "Reset the password for an specific user" +msgstr "Ripristina la password per un utente specifico" + +#: Shell/UsersShell.php:98 +msgid "User added:" +msgstr "Utente aggiunto:" + +#: Shell/UsersShell.php:99;127 +msgid "Id: {0}" +msgstr "Identificatore : {0}" + +#: Shell/UsersShell.php:100;128 +msgid "Username: {0}" +msgstr "Nome utente: {0}" + +#: Shell/UsersShell.php:101;129 +msgid "Email: {0}" +msgstr "Email : {0}" + +#: Shell/UsersShell.php:102;130 +msgid "Password: {0}" +msgstr "Password: {0}" + +#: Shell/UsersShell.php:126 +msgid "Superuser added:" +msgstr "Superuser aggiunto :" + +#: Shell/UsersShell.php:132 +msgid "Superuser could not be added:" +msgstr "Lo Superuser non puĆ² essere aggiunto :" + +#: Shell/UsersShell.php:135 +msgid "Field: {0} Error: {1}" +msgstr "Campo : {0} Errore : {1}" + +#: Shell/UsersShell.php:153;179 +msgid "Please enter a password." +msgstr "Per favore inserire una password." + +#: Shell/UsersShell.php:157 +msgid "Password changed for all users" +msgstr "Password cambiata per tutti gli utenti" + +#: Shell/UsersShell.php:158;186 +msgid "New password: {0}" +msgstr "Nuova password : {0}" + +#: Shell/UsersShell.php:176;204;282;324 +msgid "Please enter a username." +msgstr "Per favore inserire un nome utente." + +#: Shell/UsersShell.php:185 +msgid "Password changed for user: {0}" +msgstr "Password cambiata per l'utente : {0}" + +#: Shell/UsersShell.php:207 +msgid "Please enter a role." +msgstr "Per favore inserire un ruolo." + +#: Shell/UsersShell.php:213 +msgid "Role changed for user: {0}" +msgstr "Ruolo modificato per l'utente: {0}" + +#: Shell/UsersShell.php:214 +msgid "New role: {0}" +msgstr "Nuovo ruolo: {0}" + +#: Shell/UsersShell.php:229 +msgid "User was activated: {0}" +msgstr "Utente attivato: {0}" + +#: Shell/UsersShell.php:244 +msgid "User was de-activated: {0}" +msgstr "Utente disattivato: {0]" + +#: Shell/UsersShell.php:256 +msgid "Please enter a username or email." +msgstr "Per favore inserire un nome utente o email." + +#: Shell/UsersShell.php:264 +msgid "Please ask the user to check the email to continue with password reset process" +msgstr "" +"Per favore richiedere all'utente di controllare l'email per continuare con la procedura di ripristino " +"password" + +#: Shell/UsersShell.php:302 +msgid "The user was not found." +msgstr "Utente non trovato." + +#: Shell/UsersShell.php:332 +msgid "The user {0} was not deleted. Please try again" +msgstr "L'Utente {0} non ĆØ stato cancellato. Per favore riprovare" + +#: Shell/UsersShell.php:334 +msgid "The user {0} was deleted successfully" +msgstr "L'utente {0} ĆØ stato cancellato con successo" + +#: Template/Email/html/reset_password.ctp:21 Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Ciao {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Ripristina la tua password qui" + +#: Template/Email/html/reset_password.ctp:27 Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "If the link is not correcly displayed, please copy the following address in your web browser {0}" +msgstr "" +"Se il link non viene mostrato correttamente, per favore copia il seguente indirizzo nel tuo browser " +"web {0}" + +#: Template/Email/html/reset_password.ctp:30 Template/Email/html/social_account_validation.ctp:35 +#: Template/Email/html/validation.ctp:30 Template/Email/text/reset_password.ctp:24 +#: Template/Email/text/social_account_validation.ctp:26 Template/Email/text/validation.ctp:24 +msgid "Thank you" +msgstr "Grazie" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Attiva qui il tuo login social" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Attiva qui il tuo account" + +#: Template/Email/text/reset_password.ctp:22 Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Per favore copia il seguente indirizzo nel tuo browser web {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "Please copy the following address in your web browser to activate your social login {0}" +msgstr "Per favore copia il seguente indirizzo nel tuo browser web per attivare il tuo login social {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 Template/Users/index.ctp:13;26 +#: Template/Users/view.ctp:15;79 +msgid "Actions" +msgstr "Azioni" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 Template/Users/view.ctp:19 +msgid "List Users" +msgstr "Lista utenti" + +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 Template/Users/view.ctp:21 +msgid "List Accounts" +msgstr "Lista Account" + +#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 +msgid "Add User" +msgstr "Aggiunti Utente" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 Template/Users/index.ctp:22 +#: Template/Users/profile.ctp:27 Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 +msgid "Username" +msgstr "Username" + +#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 Template/Users/index.ctp:23 +#: Template/Users/profile.ctp:29 Template/Users/register.ctp:19 Template/Users/view.ctp:32 +msgid "Email" +msgstr "Email" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 Template/Users/index.ctp:24 +#: Template/Users/register.ctp:25 +msgid "First name" +msgstr "Nome" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 Template/Users/index.ctp:25 +#: Template/Users/register.ctp:26 +msgid "Last name" +msgstr "Cognome" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 Template/Users/view.ctp:44;75 +msgid "Active" +msgstr "Attivo" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 Template/Users/edit.ctp:57 +#: Template/Users/register.ctp:35 Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Inviare" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Per favore inserire la nuova password" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Password attuale" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Nuova password" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 +msgid "Confirm password" +msgstr "Conferma password" + +#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 Template/Users/view.ctp:101 +msgid "Delete" +msgstr "Cancellare" + +#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 Template/Users/view.ctp:18;101 +msgid "Are you sure you want to delete # {0}?" +msgstr "Sei sicuro di voler cancellare # {0} ?" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Modifica utente" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 +msgid "Token" +msgstr "Token" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Scadenza Token" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "API Token" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Data di attivazione" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "Data TOS" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Nuovo {0}" + +#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 +msgid "View" +msgstr "Vedere" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Cambiare la password" + +#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 +msgid "Edit" +msgstr "Modifier" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "precedente" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "successivo" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Per favore inserisci il tuo nome utente e la password" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "Ricordami" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Iscriviti" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Ripristina Password" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "Login" + +#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:24 +msgid "Change Password" +msgstr "Cambiare Password" + +#: Template/Users/profile.ctp:34 +msgid "Social Accounts" +msgstr "Account Social" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 +msgid "Avatar" +msgstr "Foto profilo" + +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 +msgid "Provider" +msgstr "Provider" + +#: Template/Users/profile.ctp:40 +msgid "Link" +msgstr "Link" + +#: Template/Users/profile.ctp:47 +msgid "Link to {0}" +msgstr "Link aĀ  {0}" + +#: Template/Users/register.ctp:20 +msgid "Password" +msgstr "Password" + +#: Template/Users/register.ctp:28 +msgid "Accept TOS conditions?" +msgstr "Accetti le condizioni TOS?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Per favore inserisci la tua email per ripristinare la password" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Rispedire Email di Convalidazione" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "Email o Username" + +#: Template/Users/view.ctp:18 +msgid "Delete User" +msgstr "Cancellare Utente" + +#: Template/Users/view.ctp:20 +msgid "New User" +msgstr "Nuovo Utente" + +#: Template/Users/view.ctp:28;67 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:34 +msgid "First Name" +msgstr "Nome" + +#: Template/Users/view.ctp:36 +msgid "Last Name" +msgstr "Cognome" + +#: Template/Users/view.ctp:40 +msgid "Api Token" +msgstr "API Token" + +#: Template/Users/view.ctp:48;74 +msgid "Token Expires" +msgstr "Scadenza Token" + +#: Template/Users/view.ctp:50 +msgid "Activation Date" +msgstr "Data di attivazione" + +#: Template/Users/view.ctp:52 +msgid "Tos Date" +msgstr "Data Tos" + +#: Template/Users/view.ctp:54;77 +msgid "Created" +msgstr "Creato il" + +#: Template/Users/view.ctp:56;78 +msgid "Modified" +msgstr "Modificato il" + +#: Template/Users/view.ctp:63 +msgid "Related Accounts" +msgstr "Account correlati" + +#: Template/Users/view.ctp:68 +msgid "User Id" +msgstr "Id Utente" + +#: Template/Users/view.ctp:71 +msgid "Reference" +msgstr "Referenza" + +#: Template/Users/view.ctp:76 +msgid "Data" +msgstr "Dati" + +#: View/Helper/UserHelper.php:46 +msgid "Sign in with" +msgstr "Registrati con" + +#: View/Helper/UserHelper.php:49 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:52 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:91 +msgid "Logout" +msgstr "Logout" + +#: View/Helper/UserHelper.php:108 +msgid "Welcome, {0}" +msgstr "Benvenuto, {0}" + +#: View/Helper/UserHelper.php:131 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "reCaptcha non configurata! Per favore configura Users.reCaptcha.key" + +#: Model/Behavior/RegisterBehavior.php:148 +msgid "This field is required" +msgstr "Questo campo ĆØ obbligatorio" + +#~ msgid "The old password does not match" +#~ msgstr "La vecchia password non corrisponde" + +#~ msgid "" +#~ "If the link is not correctly displayed, please copy the following address in your web browser {0}" +#~ msgstr "" +#~ "Se il link non viene mostrato correttamente, per favore copiare il seguente indirizzonel tuo web " +#~ "browser {0}" diff --git a/src/Locale/pl/Users.mo b/src/Locale/pl/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..c5a1c88a33dc06eb0a6a1831ac6d7b562e8516b6 GIT binary patch literal 14520 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 JbK}+W{s$j5;Di7G literal 0 HcmV?d00001 diff --git a/src/Locale/pl/Users.po b/src/Locale/pl/Users.po new file mode 100644 index 000000000..7c7834fe0 --- /dev/null +++ b/src/Locale/pl/Users.po @@ -0,0 +1,811 @@ +# LANGUAGE translation of CakePHP Application +# Copyright YEAR NAME +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2017-07-02 20:08+0200\n" +"PO-Revision-Date: 2017-07-02 20:08+0200\n" +"Last-Translator: \n" +"Language-Team: LANGUAGE \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Poedit 2.0.1\n" + +#: Auth/ApiKeyAuthenticate.php:73 +msgid "Type {0} is not valid" +msgstr "Typ {0} jest nieprawidłowy" + +#: Auth/ApiKeyAuthenticate.php:77 +msgid "Type {0} has no associated callable" +msgstr "Brak callable dla typu {0}" + +#: Auth/ApiKeyAuthenticate.php:86 +msgid "SSL is required for ApiKey Authentication" +msgstr "Uwierzytelnienie ApiKey wymaga SSL" + +#: Auth/SimpleRbacAuthorize.php:142 +msgid "" +"Missing configuration file: \"config/{0}.php\". Using default permissions" +msgstr "" +"Brak pliku konfiguracji: \"config/{0}.php\". Użyto domyślnych uprawnień" + +#: Auth/SocialAuthenticate.php:432 +msgid "Provider cannot be empty" +msgstr "Dostawca nie może być pusty" + +#: Auth/Rules/AbstractRule.php:78 +msgid "" +"Table alias is empty, please define a table alias, we could not extract a " +"default table from the request" +msgstr "Alias tabeli jest pusty, zdefiniuj alias tabeli" + +#: Auth/Rules/Owner.php:67;70 +msgid "" +"Missing column {0} in table {1} while checking ownership permissions for " +"user {2}" +msgstr "" +"Nieistniejąca kolumna {0} w tabeli {0} podczas sprawdzania uprawnień dla " +"użytkownika {2}" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Konto zostało aktywowane" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "Aktywacja konta nie powiodła się" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Nieprawidłowy token lub konto społecznościowe" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "Konto społecznościowe jest już aktywne" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "Aktywacja nie powiodła się" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "E-mail został wysłany" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "E-mail nie mĆ³gł zostać wysłany" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "Nieprawidłowe konto" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "Nie można wysłać wiadomości e-mail" + +#: Controller/Component/RememberMeComponent.php:69 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" +"Nieprawidłowa sĆ³l aplikacji, sĆ³l aplikacji powinna mieć długość co najmniej " +"256 bitĆ³w (32 bajty)" + +#: Controller/Component/UsersAuthComponent.php:178 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"Nie możesz włączyć potwierdzania kont przez e-mail jeśli opcja use_email = " +"false" + +#: Controller/Traits/LoginTrait.php:96 +msgid "Issues trying to log in with your social account" +msgstr "" +"Wystąpiły problemy z logowaniem za pośrednictwem konta społecznościowego" + +#: Controller/Traits/LoginTrait.php:101 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Podaj swĆ³j adres e-mail" + +#: Controller/Traits/LoginTrait.php:108 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Twoje konto nie zostało jeszcze aktywowane. SprawdÅŗ swoją skrzynkę odbiorczą" + +#: Controller/Traits/LoginTrait.php:110 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Konto społecznościowe nie zostało jeszcze aktywowane. SprawdÅŗ swoją pocztę e-" +"mail." + +#: Controller/Traits/LoginTrait.php:161 Controller/Traits/RegisterTrait.php:81 +msgid "Invalid reCaptcha" +msgstr "Błąd reCaptcha" + +#: Controller/Traits/LoginTrait.php:171 +msgid "You are already logged in" +msgstr "Jesteś już zalogowany" + +#: Controller/Traits/LoginTrait.php:217 +msgid "Username or password is incorrect" +msgstr "Nazwa użytkownika lub hasło jest nieprawidłowe" + +#: Controller/Traits/LoginTrait.php:238 +msgid "You've successfully logged out" +msgstr "Wylogowano" + +#: Controller/Traits/PasswordManagementTrait.php:47;76 +#: Controller/Traits/ProfileTrait.php:49 +msgid "User was not found" +msgstr "Konto użytkownika nie istnieje" + +#: Controller/Traits/PasswordManagementTrait.php:64;72;80 +msgid "Password could not be changed" +msgstr "Zmiana hasła nie powiodła się" + +#: Controller/Traits/PasswordManagementTrait.php:68 +msgid "Password has been changed successfully" +msgstr "Hasło zostało zmienione" + +#: Controller/Traits/PasswordManagementTrait.php:78 +msgid "{0}" +msgstr "{0}" + +#: Controller/Traits/PasswordManagementTrait.php:120 +msgid "Please check your email to continue with password reset process" +msgstr "Aby dokończyć zmianę hasła, sprawdÅŗ swoją pocztę e-mail." + +#: Controller/Traits/PasswordManagementTrait.php:123 Shell/UsersShell.php:267 +msgid "The password token could not be generated. Please try again" +msgstr "Nie można wygenerować tokenu. SprĆ³buj ponownie" + +#: Controller/Traits/PasswordManagementTrait.php:129 +#: Controller/Traits/UserValidationTrait.php:100 +msgid "User {0} was not found" +msgstr "Nie znaleziono użytkownika {0}" + +#: Controller/Traits/PasswordManagementTrait.php:131 +msgid "The user is not active" +msgstr "Konto użytkownika nie jest aktywne" + +#: Controller/Traits/PasswordManagementTrait.php:133 +#: Controller/Traits/UserValidationTrait.php:95;104 +msgid "Token could not be reset" +msgstr "Nie można zresetować tokenu" + +#: Controller/Traits/ProfileTrait.php:53 +msgid "Not authorized, please login first" +msgstr "Wymagane logowanie" + +#: Controller/Traits/RegisterTrait.php:42 +msgid "You must log out to register a new user account" +msgstr "Wyloguj się aby utworzyć nowe konto" + +#: Controller/Traits/RegisterTrait.php:88 +msgid "The user could not be saved" +msgstr "Nie można utworzyć konta" + +#: Controller/Traits/RegisterTrait.php:122 +msgid "You have registered successfully, please log in" +msgstr "Rejestracja zakończona sukcesem, możesz się zalogować" + +#: Controller/Traits/RegisterTrait.php:124 +msgid "Please validate your account before log in" +msgstr "PotwierdÅŗ swoje konto przed logowaniem" + +#: Controller/Traits/SimpleCrudTrait.php:76;106 +msgid "The {0} has been saved" +msgstr "{0} został zapisany" + +#: Controller/Traits/SimpleCrudTrait.php:80;110 +msgid "The {0} could not be saved" +msgstr "{0} nie mĆ³gł zostać zapisany" + +#: Controller/Traits/SimpleCrudTrait.php:130 +msgid "The {0} has been deleted" +msgstr "{0} został usunięty" + +#: Controller/Traits/SimpleCrudTrait.php:132 +msgid "The {0} could not be deleted" +msgstr "{0} nie mĆ³gł zostać usunięty" + +#: Controller/Traits/SocialTrait.php:39 +msgid "The reCaptcha could not be validated" +msgstr "Błąd walidacji reCaptcha" + +#: Controller/Traits/UserValidationTrait.php:42 +msgid "User account validated successfully" +msgstr "Konto użytkownika zostało aktywowane" + +#: Controller/Traits/UserValidationTrait.php:44 +msgid "User account could not be validated" +msgstr "Aktywacja konta nie powiodła się" + +#: Controller/Traits/UserValidationTrait.php:47 +msgid "User already active" +msgstr "Konto jest już aktywne" + +#: Controller/Traits/UserValidationTrait.php:53 +msgid "Reset password token was validated successfully" +msgstr "Token zmiany hasła został zatwierdzony" + +#: Controller/Traits/UserValidationTrait.php:58 +msgid "Reset password token could not be validated" +msgstr "Błąd podczas walidacji tokenu zmiany hasła" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Invalid validation type" +msgstr "Nieprawidłowy typ walidacji" + +#: Controller/Traits/UserValidationTrait.php:65 +msgid "Invalid token or user account already validated" +msgstr "Nieprawidłowy token lub konto jest już aktywne" + +#: Controller/Traits/UserValidationTrait.php:67 +msgid "Token already expired" +msgstr "Token wygasł" + +#: Controller/Traits/UserValidationTrait.php:93 +msgid "Token has been reset successfully. Please check your email." +msgstr "Token został zresetowany. SprawdÅŗ swoją pocztę e-mail." + +#: Controller/Traits/UserValidationTrait.php:102 +msgid "User {0} is already active" +msgstr "Użytkownik {0} jest już aktywny" + +#: Email/EmailSender.php:39 +msgid "Your account validation link" +msgstr "TwĆ³j link aktywacyjny" + +#: Mailer/UsersMailer.php:55 +msgid "{0}Your reset password link" +msgstr "{0}TwĆ³j link zmiany hasła" + +#: Mailer/UsersMailer.php:78 +msgid "{0}Your social account validation link" +msgstr "{0} TwĆ³j link aktywacyjny" + +#: Model/Behavior/PasswordBehavior.php:56 +msgid "Reference cannot be null" +msgstr "Wartość nie może być pusta" + +#: Model/Behavior/PasswordBehavior.php:61 +msgid "Token expiration cannot be empty" +msgstr "Parametr 'expiration' nie może być pusty" + +#: Model/Behavior/PasswordBehavior.php:67;116 +msgid "User not found" +msgstr "Nie odnaleziono użytkownika" + +#: Model/Behavior/PasswordBehavior.php:71 +#: Model/Behavior/RegisterBehavior.php:111 +msgid "User account already validated" +msgstr "Konto użytkownika zostało już aktywowane" + +#: Model/Behavior/PasswordBehavior.php:78 +msgid "User not active" +msgstr "Użytkownik nie jest aktywny" + +#: Model/Behavior/PasswordBehavior.php:121 +msgid "The current password does not match" +msgstr "Bieżące hasło nie jest prawidłowe" + +#: Model/Behavior/PasswordBehavior.php:124 +msgid "You cannot use the current password as the new one" +msgstr "Nowe hasło nie może być takie same jak obecne" + +#: Model/Behavior/RegisterBehavior.php:89 +msgid "User not found for the given token and email." +msgstr "Nie odnaleziono użytkownika dla danego tokenu i adresu e-mail." + +#: Model/Behavior/RegisterBehavior.php:92 +msgid "Token has already expired user with no token" +msgstr "Token wygasł" + +#: Model/Behavior/SocialAccountBehavior.php:102;129 +msgid "Account already validated" +msgstr "Konto zostało już aktywowane" + +#: Model/Behavior/SocialAccountBehavior.php:105;132 +msgid "Account not found for the given token and email." +msgstr "Nie odnaleziono konta dla danego tokenu i adresu e-mail." + +#: Model/Behavior/SocialBehavior.php:56 +msgid "Unable to login user with reference {0}" +msgstr "Nie można zalogować użytkownika o loginie {0}" + +#: Model/Behavior/SocialBehavior.php:98 +msgid "Email not present" +msgstr "Brak adresu e-mail" + +#: Model/Table/UsersTable.php:82 +msgid "Your password does not match your confirm password. Please try again" +msgstr "Podane hasła rĆ³Å¼nią się. SprĆ³buj ponownie." + +#: Model/Table/UsersTable.php:175 +msgid "Username already exists" +msgstr "Nazwa użytkownika już istnieje" + +#: Model/Table/UsersTable.php:181 +msgid "Email already exists" +msgstr "Adres e-mail już istnieje" + +#: Model/Table/UsersTable.php:214 +msgid "Missing 'username' in options data" +msgstr "Brak klucza 'username'" + +#: Shell/UsersShell.php:54 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Narzędzia dla CakeDC Users Plugin" + +#: Shell/UsersShell.php:55 +msgid "Activate an specific user" +msgstr "Aktywuj użytkownika" + +#: Shell/UsersShell.php:56 +msgid "Add a new superadmin user for testing purposes" +msgstr "Dodaj konto administracyjne do celĆ³w testowych" + +#: Shell/UsersShell.php:57 +msgid "Add a new user" +msgstr "Dodaj użytkownika" + +#: Shell/UsersShell.php:58 +msgid "Change the role for an specific user" +msgstr "Zmień rolę konkretnego użytkownika" + +#: Shell/UsersShell.php:59 +msgid "Deactivate an specific user" +msgstr "Deaktywuj użytkownika" + +#: Shell/UsersShell.php:60 +msgid "Delete an specific user" +msgstr "Usuń użytkownika" + +#: Shell/UsersShell.php:61 +msgid "Reset the password via email" +msgstr "Zresetuj hasło przez e-mail" + +#: Shell/UsersShell.php:62 +msgid "Reset the password for all users" +msgstr "Zresetuj hasło dla wszystkich użytkownikĆ³w" + +#: Shell/UsersShell.php:63 +msgid "Reset the password for an specific user" +msgstr "Zresetuj hasło dla konkretnego użytkownika" + +#: Shell/UsersShell.php:98 +msgid "User added:" +msgstr "Dodano użytkownika:" + +#: Shell/UsersShell.php:99;127 +msgid "Id: {0}" +msgstr "Id: {0}" + +#: Shell/UsersShell.php:100;128 +msgid "Username: {0}" +msgstr "Nazwa użytkownika: {0}" + +#: Shell/UsersShell.php:101;129 +msgid "Email: {0}" +msgstr "E-mail: {0}" + +#: Shell/UsersShell.php:102;130 +msgid "Password: {0}" +msgstr "Hasło: {0}" + +#: Shell/UsersShell.php:126 +msgid "Superuser added:" +msgstr "Dodano super użytkownika:" + +#: Shell/UsersShell.php:132 +msgid "Superuser could not be added:" +msgstr "Nie można dodać super użytkownika:" + +#: Shell/UsersShell.php:135 +msgid "Field: {0} Error: {1}" +msgstr "Pole: {0} Błąd: {1}" + +#: Shell/UsersShell.php:153;179 +msgid "Please enter a password." +msgstr "Podaj hasło." + +#: Shell/UsersShell.php:157 +msgid "Password changed for all users" +msgstr "Zmieniono hasło dla wszystkich użytkownikĆ³w" + +#: Shell/UsersShell.php:158;186 +msgid "New password: {0}" +msgstr "Nowe hasło: {0}" + +#: Shell/UsersShell.php:176;204;282;324 +msgid "Please enter a username." +msgstr "Podaj nazwę użytkownika." + +#: Shell/UsersShell.php:185 +msgid "Password changed for user: {0}" +msgstr "Zmieniono hasło dla użytkownika: {0}" + +#: Shell/UsersShell.php:207 +msgid "Please enter a role." +msgstr "Podaj rolę." + +#: Shell/UsersShell.php:213 +msgid "Role changed for user: {0}" +msgstr "Zmieniono rolę dla użytkownika: {0}" + +#: Shell/UsersShell.php:214 +msgid "New role: {0}" +msgstr "Nowa rola: {0}" + +#: Shell/UsersShell.php:229 +msgid "User was activated: {0}" +msgstr "Użytkownik został aktywowany: {0}" + +#: Shell/UsersShell.php:244 +msgid "User was de-activated: {0}" +msgstr "Użytkownik został zdeaktywowany: {0}" + +#: Shell/UsersShell.php:256 +msgid "Please enter a username or email." +msgstr "Podaj nazwę użytkownika lub hasło." + +#: Shell/UsersShell.php:264 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "Aby dokończyć zmianę hasła, sprawdÅŗ swoją pocztę e-mail" + +#: Shell/UsersShell.php:302 +msgid "The user was not found." +msgstr "Nie odnaleziono użytkownika." + +#: Shell/UsersShell.php:332 +msgid "The user {0} was not deleted. Please try again" +msgstr "Usuwanie użytkownika {0} nie powiodło się. SprĆ³buj ponownie" + +#: Shell/UsersShell.php:334 +msgid "The user {0} was deleted successfully" +msgstr "Użytkownik {0} został usunięty" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Witaj {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Kontynuuj zmianę hasła" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correcly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Jeśli link nie jest wyświetlony poprawnie, skopiuj łącze do paska adresu " +"przeglądarki {0}" + +#: Template/Email/html/reset_password.ctp:30 +#: Template/Email/html/social_account_validation.ctp:35 +#: Template/Email/html/validation.ctp:30 +#: Template/Email/text/reset_password.ctp:24 +#: Template/Email/text/social_account_validation.ctp:26 +#: Template/Email/text/validation.ctp:24 +msgid "Thank you" +msgstr "Dziękujemy" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Aktywuj konto" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Aktywuj konto" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Skopiuj łącze do paska adresu przeglądarki {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "Skopiuj łącze do paska adresu przeglądarki, aby aktywować konto {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:15 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15;79 +msgid "Actions" +msgstr "Akcje" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:26 +#: Template/Users/view.ctp:19 +msgid "List Users" +msgstr "Użytkownicy" + +#: Template/Users/add.ctp:16 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:21 +msgid "List Accounts" +msgstr "Konta" + +#: Template/Users/add.ctp:22 Template/Users/register.ctp:16 +msgid "Add User" +msgstr "Dodaj użytkownika" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:27 +#: Template/Users/register.ctp:18 Template/Users/view.ctp:30;70 +msgid "Username" +msgstr "Nazwa użytkownika" + +#: Template/Users/add.ctp:25 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:29 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:32 +msgid "Email" +msgstr "E-mail" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:25 +msgid "First name" +msgstr "Imię" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:26 +msgid "Last name" +msgstr "Nazwisko" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:44;75 +msgid "Active" +msgstr "Aktywny" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:35 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Wyślij" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Podaj nowe hasło" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Obecne hasło" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Nowe hasło" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:23 +msgid "Confirm password" +msgstr "PotwierdÅŗ hasło" + +#: Template/Users/edit.ctp:20 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:101 +msgid "Delete" +msgstr "Usuń" + +#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:18;101 +msgid "Are you sure you want to delete # {0}?" +msgstr "Czy na pewno usunąć # {0}?" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Edytuj użytkownika" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:38;73 +msgid "Token" +msgstr "Token" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Token wygasa" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "API token" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Data aktywacji" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "Data (TOS)" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Nowy {0}" + +#: Template/Users/index.ctp:37 Template/Users/view.ctp:97 +msgid "View" +msgstr "SzczegĆ³Å‚y" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Zmień hasło" + +#: Template/Users/index.ctp:39 Template/Users/view.ctp:99 +msgid "Edit" +msgstr "Edytuj" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "poprzednia" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "następna" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Podaj nazwę użytkownika i hasło" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "Zapamiętaj" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Rejestracja" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Zresetuj hasło" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "Zaloguj" + +#: Template/Users/profile.ctp:18 View/Helper/UserHelper.php:51 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:24 +msgid "Change Password" +msgstr "Zmień hasło" + +#: Template/Users/profile.ctp:34 +msgid "Social Accounts" +msgstr "Konta społecznościowe" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:72 +msgid "Avatar" +msgstr "Avatar" + +#: Template/Users/profile.ctp:39 Template/Users/view.ctp:69 +msgid "Provider" +msgstr "Dostawca" + +#: Template/Users/profile.ctp:40 +msgid "Link" +msgstr "Link" + +#: Template/Users/profile.ctp:47 +msgid "Link to {0}" +msgstr "Link do {0}" + +#: Template/Users/register.ctp:20 +msgid "Password" +msgstr "Hasło" + +#: Template/Users/register.ctp:28 +msgid "Accept TOS conditions?" +msgstr "Akceptuję warunki użytkowania" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "W celu zmiany hasła podaj adres e-mail" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Ponownie wyślij e-mail aktywacyjny" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "E-mail lub nazwa użytkownika" + +#: Template/Users/view.ctp:18 +msgid "Delete User" +msgstr "Usuń użytkownika" + +#: Template/Users/view.ctp:20 +msgid "New User" +msgstr "Nowy użytkownik" + +#: Template/Users/view.ctp:28;67 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:34 +msgid "First Name" +msgstr "Imię" + +#: Template/Users/view.ctp:36 +msgid "Last Name" +msgstr "Nazwisko" + +#: Template/Users/view.ctp:40 +msgid "Api Token" +msgstr "Api Token" + +#: Template/Users/view.ctp:48;74 +msgid "Token Expires" +msgstr "Token wygasa" + +#: Template/Users/view.ctp:50 +msgid "Activation Date" +msgstr "Data aktywacji" + +#: Template/Users/view.ctp:52 +msgid "Tos Date" +msgstr "Data (TOS)" + +#: Template/Users/view.ctp:54;77 +msgid "Created" +msgstr "Utworzono" + +#: Template/Users/view.ctp:56;78 +msgid "Modified" +msgstr "Zmodyfikowano" + +#: Template/Users/view.ctp:63 +msgid "Related Accounts" +msgstr "Powiązane konta" + +#: Template/Users/view.ctp:68 +msgid "User Id" +msgstr "Id użytkownika" + +#: Template/Users/view.ctp:71 +msgid "Reference" +msgstr "Reference" + +#: Template/Users/view.ctp:76 +msgid "Data" +msgstr "Dane" + +#: View/Helper/UserHelper.php:46 +msgid "Sign in with" +msgstr "Zaloguj się za pomocą" + +#: View/Helper/UserHelper.php:49 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:52 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:91 +msgid "Logout" +msgstr "Wyloguj" + +#: View/Helper/UserHelper.php:108 +msgid "Welcome, {0}" +msgstr "Witaj, {0}" + +#: View/Helper/UserHelper.php:131 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"reCaptcha nie zostało skonfigurowane! Skonfiguruj opcję Users.reCaptcha.key" + +#: Model/Behavior/RegisterBehavior.php:148 +msgid "This field is required" +msgstr "Pole wymagane" diff --git a/src/Locale/pt_BR/Users.mo b/src/Locale/pt_BR/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..5cbc087b8fb6ad1fc6defdce71a871a71909e486 GIT binary patch literal 15088 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\n" +"Language-Team: CakeDC \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 2.0.4\n" + +#: Auth/SocialAuthenticate.php:456 +msgid "Provider cannot be empty" +msgstr "O provedor nĆ£o pode ser vazio" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Conta validada com ĆŖxito" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "A conta nĆ£o pode ser validada" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Token e/ou conta social invĆ”lido(s)" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "Conta social jĆ” ativa" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "A conta social nĆ£o pode ser validada" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "Email enviado com sucesso" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "O email nĆ£o pode ser enviado" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "Conta invĆ”lida" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "O email nĆ£o pode ser reenviado" + +#: Controller/Component/RememberMeComponent.php:68 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" +"Salt da aplicaĆ§Ć£o invĆ”lido, o salt da aplicaĆ§Ć£o deve ser de pelo menos 256 " +"bits (32 bytes)" + +#: Controller/Component/UsersAuthComponent.php:204 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"VocĆŖ nĆ£o pode habilitar o fluxo de validaĆ§Ć£o por email se use_email for false" + +#: Controller/Traits/LinkSocialTrait.php:54 +msgid "Could not associate account, please try again." +msgstr "NĆ£o foi possĆ­vel associar a conta, tente novamente." + +#: Controller/Traits/LinkSocialTrait.php:77 +msgid "Social account was associated." +msgstr "A conta social foi associada." + +#: Controller/Traits/LoginTrait.php:104 +msgid "Issues trying to log in with your social account" +msgstr "Problemas ao tentar autenticar a partir da sua conta social" + +#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Por favor indique seu email" + +#: Controller/Traits/LoginTrait.php:120 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Seu usuĆ”rio ainda nĆ£o foi validado. Por favor, verifique sua caixa de " +"entrada para instruƧƵes" + +#: Controller/Traits/LoginTrait.php:125 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Sua conta social ainda nĆ£o foi validada. Por favor, verifique sua caixa de " +"entrada para instruƧƵes" + +#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 +msgid "Invalid reCaptcha" +msgstr "ReCaptcha invĆ”lido" + +#: Controller/Traits/LoginTrait.php:191 +msgid "You are already logged in" +msgstr "VocĆŖ jĆ” estĆ” autenticado" + +#: Controller/Traits/LoginTrait.php:212 +msgid "Please enable Google Authenticator first." +msgstr "Por favor habilite o Google Authenticator primeiro." + +#: Controller/Traits/LoginTrait.php:287 +msgid "Verification code is invalid. Try again" +msgstr "CĆ³digo de verificaĆ§Ć£o Ć© invĆ”lido. Tente novamente" + +#: Controller/Traits/LoginTrait.php:340 +msgid "Username or password is incorrect" +msgstr "Nome de usuĆ”rio e/ou senha incorreto(s)" + +#: Controller/Traits/LoginTrait.php:363 +msgid "You've successfully logged out" +msgstr "VocĆŖ desconectou-se com ĆŖxito" + +#: Controller/Traits/PasswordManagementTrait.php:49;82 +#: Controller/Traits/ProfileTrait.php:50 +msgid "User was not found" +msgstr "O usuĆ”rio nĆ£o foi encontrado" + +#: Controller/Traits/PasswordManagementTrait.php:70;78;86 +msgid "Password could not be changed" +msgstr "A senha nĆ£o pode ser alterada" + +#: Controller/Traits/PasswordManagementTrait.php:74 +msgid "Password has been changed successfully" +msgstr "Senha alterada com ĆŖxito" + +#: Controller/Traits/PasswordManagementTrait.php:84 +msgid "{0}" +msgstr "{0}" + +#: Controller/Traits/PasswordManagementTrait.php:127 +msgid "Please check your email to continue with password reset process" +msgstr "" +"Por favor, verifique seu email para continuar o processo de redefiniĆ§Ć£o de " +"senha" + +#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 +msgid "The password token could not be generated. Please try again" +msgstr "O token de senha nĆ£o pode ser gerado. Por favor, tente novamente" + +#: Controller/Traits/PasswordManagementTrait.php:136 +#: Controller/Traits/UserValidationTrait.php:107 +msgid "User {0} was not found" +msgstr "O usuĆ”rio {0} nĆ£o foi encontrado" + +#: Controller/Traits/PasswordManagementTrait.php:138 +msgid "The user is not active" +msgstr "O usuĆ”rio nĆ£o estĆ” ativo" + +#: Controller/Traits/PasswordManagementTrait.php:140 +#: Controller/Traits/UserValidationTrait.php:102;111 +msgid "Token could not be reset" +msgstr "O token nĆ£o pode ser redefinido" + +#: Controller/Traits/PasswordManagementTrait.php:164 +msgid "Google Authenticator token was successfully reset" +msgstr "O token do Google Authenticator foi reiniciado com sucesso" + +#: Controller/Traits/ProfileTrait.php:54 +msgid "Not authorized, please login first" +msgstr "NĆ£o autorizado, por favor, autentique-se primeiro" + +#: Controller/Traits/RegisterTrait.php:43 +msgid "You must log out to register a new user account" +msgstr "VocĆŖ deve deslogar para registrar uma nova conta de usuĆ”rio" + +#: Controller/Traits/RegisterTrait.php:89 +msgid "The user could not be saved" +msgstr "O usuĆ”rio nĆ£o pode ser salvo" + +#: Controller/Traits/RegisterTrait.php:123 +msgid "You have registered successfully, please log in" +msgstr "VocĆŖ registrou-se com sucesso, por favor, autentique-se" + +#: Controller/Traits/RegisterTrait.php:125 +msgid "Please validate your account before log in" +msgstr "Por favor, valide sua conta antes de autenticar" + +#: Controller/Traits/SimpleCrudTrait.php:77;107 +msgid "The {0} has been saved" +msgstr "O {0} foi salvo" + +#: Controller/Traits/SimpleCrudTrait.php:81;111 +msgid "The {0} could not be saved" +msgstr "O {0} nĆ£o pode ser salvo" + +#: Controller/Traits/SimpleCrudTrait.php:131 +msgid "The {0} has been deleted" +msgstr "O {0} foi deletado" + +#: Controller/Traits/SimpleCrudTrait.php:133 +msgid "The {0} could not be deleted" +msgstr "O {0} nĆ£o pode ser deletado" + +#: Controller/Traits/SocialTrait.php:40 +msgid "The reCaptcha could not be validated" +msgstr "O reCaptcha nĆ£o pode ser validado" + +#: Controller/Traits/UserValidationTrait.php:43 +msgid "User account validated successfully" +msgstr "Conta de usuĆ”rio validada com ĆŖxito" + +#: Controller/Traits/UserValidationTrait.php:45 +msgid "User account could not be validated" +msgstr "A conta de usuĆ”rio nĆ£o pode ser validada" + +#: Controller/Traits/UserValidationTrait.php:48 +msgid "User already active" +msgstr "UsuĆ”rio jĆ” ativo" + +#: Controller/Traits/UserValidationTrait.php:54 +msgid "Reset password token was validated successfully" +msgstr "Token de redefiniĆ§Ć£o de senha validado com ĆŖxito" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Reset password token could not be validated" +msgstr "O token de redefiniĆ§Ć£o de senha nĆ£o pode ser validado" + +#: Controller/Traits/UserValidationTrait.php:66 +msgid "Invalid validation type" +msgstr "Tipo de validaĆ§Ć£o invĆ”lido" + +#: Controller/Traits/UserValidationTrait.php:69 +msgid "Invalid token or user account already validated" +msgstr "Token invĆ”lido ou conta jĆ” validada" + +#: Controller/Traits/UserValidationTrait.php:71 +msgid "Token already expired" +msgstr "Token expirado" + +#: Controller/Traits/UserValidationTrait.php:97 +msgid "Token has been reset successfully. Please check your email." +msgstr "O token foi redefinido com ĆŖxito. Por favor, verifique seu email." + +#: Controller/Traits/UserValidationTrait.php:109 +msgid "User {0} is already active" +msgstr "O usuĆ”rio {0} jĆ” estĆ” ativo" + +#: Mailer/UsersMailer.php:34 +msgid "Your account validation link" +msgstr "Seu link de validaĆ§Ć£o da conta" + +#: Mailer/UsersMailer.php:52 +msgid "{0}Your reset password link" +msgstr "{0}Seu link de redefiniĆ§Ć£o de senha" + +#: Mailer/UsersMailer.php:75 +msgid "{0}Your social account validation link" +msgstr "{0}Seu link de validaĆ§Ć£o da conta social" + +#: Model/Behavior/AuthFinderBehavior.php:49 +msgid "Missing 'username' in options data" +msgstr "'username' ausente nas opƧƵes" + +#: Model/Behavior/LinkSocialBehavior.php:53 +msgid "Social account already associated to another user" +msgstr "Conta social jĆ” estĆ” associada a outro usuĆ”rio" + +#: Model/Behavior/PasswordBehavior.php:45 +msgid "Reference cannot be null" +msgstr "A referĆŖncia nĆ£o pode ser nula" + +#: Model/Behavior/PasswordBehavior.php:50 +msgid "Token expiration cannot be empty" +msgstr "A expiraĆ§Ć£o do token nĆ£o pode ser vazia" + +#: Model/Behavior/PasswordBehavior.php:56;117 +msgid "User not found" +msgstr "UsuĆ”rio nĆ£o encontrado" + +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112;205 +msgid "User account already validated" +msgstr "Conta de usuĆ”rio jĆ” validada" + +#: Model/Behavior/PasswordBehavior.php:67 +msgid "User not active" +msgstr "UsuĆ”rio inativo" + +#: Model/Behavior/PasswordBehavior.php:122 +msgid "The current password does not match" +msgstr "A senha atual nĆ£o corresponde" + +#: Model/Behavior/PasswordBehavior.php:125 +msgid "You cannot use the current password as the new one" +msgstr "VocĆŖ nĆ£o pode usar a senha atual como nova senha" + +#: Model/Behavior/RegisterBehavior.php:90 +msgid "User not found for the given token and email." +msgstr "UsuĆ”rio nĆ£o encontrado com a combinaĆ§Ć£o de token e email" + +#: Model/Behavior/RegisterBehavior.php:93 +msgid "Token has already expired user with no token" +msgstr "Token expirado, usuĆ”rio sem token" + +#: Model/Behavior/SocialAccountBehavior.php:103;130 +msgid "Account already validated" +msgstr "Conta jĆ” validada" + +#: Model/Behavior/SocialAccountBehavior.php:106;133 +msgid "Account not found for the given token and email." +msgstr "Conta nĆ£o encontrada com a combinaĆ§Ć£o de token e email" + +#: Model/Behavior/SocialBehavior.php:82 +msgid "Unable to login user with reference {0}" +msgstr "Incapaz de autenticar usuĆ”rio com a referĆŖncia {0}" + +#: Model/Behavior/SocialBehavior.php:121 +msgid "Email not present" +msgstr "Email ausente" + +#: Model/Table/UsersTable.php:81 +msgid "Your password does not match your confirm password. Please try again" +msgstr "" +"Sua senha nĆ£o corresponde com a confirmaĆ§Ć£o. Por favor, tente novamente" + +#: Model/Table/UsersTable.php:173 +msgid "Username already exists" +msgstr "Nome de usuĆ”rio em uso" + +#: Model/Table/UsersTable.php:179 +msgid "Email already exists" +msgstr "Email em uso" + +#: Shell/UsersShell.php:58 +msgid "Utilities for CakeDC Users Plugin" +msgstr "UtilitĆ”rios para CakeDC Users Plugin" + +#: Shell/UsersShell.php:60 +msgid "Activate an specific user" +msgstr "Ativar um usuĆ”rio especĆ­fico" + +#: Shell/UsersShell.php:63 +msgid "Add a new superadmin user for testing purposes" +msgstr "Adicionar um novo usuĆ”rio superadmin para fins de testes" + +#: Shell/UsersShell.php:66 +msgid "Add a new user" +msgstr "Adicionar um novo usuĆ”rio" + +#: Shell/UsersShell.php:69 +msgid "Change the role for an specific user" +msgstr "Alterar o role de um usuĆ”rio especĆ­fico" + +#: Shell/UsersShell.php:72 +msgid "Deactivate an specific user" +msgstr "Desativar um usuĆ”rio especĆ­fico" + +#: Shell/UsersShell.php:75 +msgid "Delete an specific user" +msgstr "Deletar um usuĆ”rio especĆ­fico" + +#: Shell/UsersShell.php:78 +msgid "Reset the password via email" +msgstr "Redefinir a senha via email" + +#: Shell/UsersShell.php:81 +msgid "Reset the password for all users" +msgstr "Redefinir a senha de todos usuĆ”rios" + +#: Shell/UsersShell.php:84 +msgid "Reset the password for an specific user" +msgstr "Redefinir a senha de um usuĆ”rio especĆ­fico" + +#: Shell/UsersShell.php:133;159 +msgid "Please enter a password." +msgstr "Por favor, indique uma senha." + +#: Shell/UsersShell.php:137 +msgid "Password changed for all users" +msgstr "As senhas de todos usuĆ”rios foram alteradas" + +#: Shell/UsersShell.php:138;166 +msgid "New password: {0}" +msgstr "Nova senha: {0}" + +#: Shell/UsersShell.php:156;184;262;359 +msgid "Please enter a username." +msgstr "Por favor, indique um nome de usuĆ”rio." + +#: Shell/UsersShell.php:165 +msgid "Password changed for user: {0}" +msgstr "Senha alterada para usuĆ”rio: {0}" + +#: Shell/UsersShell.php:187 +msgid "Please enter a role." +msgstr "Por favor, indique um papel." + +#: Shell/UsersShell.php:193 +msgid "Role changed for user: {0}" +msgstr "Papel alterado para usuĆ”rio: {0}" + +#: Shell/UsersShell.php:194 +msgid "New role: {0}" +msgstr "Novo papel: {0}" + +#: Shell/UsersShell.php:209 +msgid "User was activated: {0}" +msgstr "UsuĆ”rio ativado: {0}" + +#: Shell/UsersShell.php:224 +msgid "User was de-activated: {0}" +msgstr "UsuĆ”rio desativado: {0}" + +#: Shell/UsersShell.php:236 +msgid "Please enter a username or email." +msgstr "Por favor, indique um nome de usuĆ”rio ou senha." + +#: Shell/UsersShell.php:244 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"Por favor, peƧa ao usuĆ”rio para verificar seu email para continuar o " +"processo de redefiniĆ§Ć£o de senha" + +#: Shell/UsersShell.php:308 +msgid "Superuser added:" +msgstr "SuperusuĆ”rio adicionado:" + +#: Shell/UsersShell.php:310 +msgid "User added:" +msgstr "UsuĆ”rio adicionado:" + +#: Shell/UsersShell.php:312 +msgid "Id: {0}" +msgstr "Id: {0}" + +#: Shell/UsersShell.php:313 +msgid "Username: {0}" +msgstr "Nome de usuĆ”rio: {0}" + +#: Shell/UsersShell.php:314 +msgid "Email: {0}" +msgstr "Email: {0}" + +#: Shell/UsersShell.php:315 +msgid "Role: {0}" +msgstr "Papel: {0}" + +#: Shell/UsersShell.php:316 +msgid "Password: {0}" +msgstr "Senha: {0}" + +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "UsuĆ”rio nĆ£o pĆ“de ser adicionado:" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" +msgstr "Campo: {0} Erro: {1}" + +#: Shell/UsersShell.php:337 +msgid "The user was not found." +msgstr "O usuĆ”rio nĆ£o foi encontrado." + +#: Shell/UsersShell.php:367 +msgid "The user {0} was not deleted. Please try again" +msgstr "O usuĆ”rio {0} nĆ£o foi deletado. Por favor, tente novamente" + +#: Shell/UsersShell.php:369 +msgid "The user {0} was deleted successfully" +msgstr "O usuĆ”rio {0} foi deletado com ĆŖxito" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "OlĆ” {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Redefina sua senha aqui" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Se o link nĆ£o estiver sendo exibido corretamente, por favor, copie o " +"seguinte endereƧo em seu navegador {0}" + +#: Template/Email/html/reset_password.ctp:34 +#: Template/Email/html/social_account_validation.ctp:39 +#: Template/Email/html/validation.ctp:34 +#: Template/Email/text/reset_password.ctp:28 +#: Template/Email/text/social_account_validation.ctp:30 +#: Template/Email/text/validation.ctp:28 +msgid "Thank you" +msgstr "Obrigado" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Ative sua autenticaĆ§Ć£o social aqui" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Ative sua conta aqui" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Por favor, copie o endereƧo a seguir em seu navegador {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"Por favor, copie o endereƧo a seguir em seu navegador para ativar sua " +"autenticaĆ§Ć£o social {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 +msgid "Actions" +msgstr "AƧƵes" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:23 +msgid "List Users" +msgstr "Listar usuĆ”rios" + +#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 +msgid "Add User" +msgstr "Adicionar usuĆ”rio" + +#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 +msgid "Username" +msgstr "Nome de usuĆ”rio" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 +msgid "Email" +msgstr "Email" + +#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 +msgid "Password" +msgstr "Senha" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 +msgid "First name" +msgstr "Nome" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 +msgid "Last name" +msgstr "Sobrenome" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:49;74 +msgid "Active" +msgstr "Ativo" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Enviar" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Por favor, indique a nova senha" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Senha atual" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Nova senha" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 +msgid "Confirm password" +msgstr "Confirmar senha" + +#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 +msgid "Delete" +msgstr "Deletar" + +#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:21 +msgid "Are you sure you want to delete # {0}?" +msgstr "Tem certeza que deseja deletar # {0}?" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Editar usuĆ”rio" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 +msgid "Token" +msgstr "Token" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Token expira" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "Token da API" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Data de ativaĆ§Ć£o" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "Data TOS" + +#: Template/Users/edit.ctp:63 +msgid "Reset Google Authenticator Token" +msgstr "Redefir Token do Google Authenticator" + +#: Template/Users/edit.ctp:69 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "VocĆŖ tem certeza que deseja redefinir o token para o usuĆ”rio ā€œ{0}ā€?" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Novo {0}" + +#: Template/Users/index.ctp:37 +msgid "View" +msgstr "Visualizar" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Alterar senha" + +#: Template/Users/index.ctp:39 +msgid "Edit" +msgstr "Editar" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "anterior" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "prĆ³ximo" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Por favor, indique seu nome de usuĆ”rio e senha" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "Lembrar" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Registrar" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Resetar Senha" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "Autenticar" + +#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:27 +msgid "Change Password" +msgstr "Mudar senha" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 +msgid "Social Accounts" +msgstr "Contas sociais" + +#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 +msgid "Avatar" +msgstr "Avatar" + +#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 +msgid "Provider" +msgstr "Provedor" + +#: Template/Users/profile.ctp:44 +msgid "Link" +msgstr "Link" + +#: Template/Users/profile.ctp:51 +msgid "Link to {0}" +msgstr "Link para {0}" + +#: Template/Users/register.ctp:29 +msgid "Accept TOS conditions?" +msgstr "Concordar com Termos de Uso?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Por favor, indique seu email para redefinir sua senha" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Reenviar email de validaĆ§Ć£o" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "Email ou nome de usuĆ”rio" + +#: Template/Users/verify.ctp:13 +msgid "Verification Code" +msgstr "CĆ³digo de verificaĆ§Ć£o" + +#: Template/Users/verify.ctp:15 +msgid "" +" " +"Verify" +msgstr "" +" Verificar" + +#: Template/Users/view.ctp:19 +msgid "Delete User" +msgstr "Deletar usuĆ”rio" + +#: Template/Users/view.ctp:24 +msgid "New User" +msgstr "Novo usuĆ”rio" + +#: Template/Users/view.ctp:31 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:37 +msgid "First Name" +msgstr "Nome" + +#: Template/Users/view.ctp:39 +msgid "Last Name" +msgstr "Sobrenome" + +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "Papel" + +#: Template/Users/view.ctp:45 +msgid "Api Token" +msgstr "Api Token" + +#: Template/Users/view.ctp:53 +msgid "Token Expires" +msgstr "ExpiraĆ§Ć£o do token" + +#: Template/Users/view.ctp:55 +msgid "Activation Date" +msgstr "Data de ativaĆ§Ć£o" + +#: Template/Users/view.ctp:57 +msgid "Tos Date" +msgstr "Data TOS" + +#: Template/Users/view.ctp:59;75 +msgid "Created" +msgstr "Criado" + +#: Template/Users/view.ctp:61;76 +msgid "Modified" +msgstr "Modificado" + +#: View/Helper/UserHelper.php:45 +msgid "Sign in with" +msgstr "Logar com" + +#: View/Helper/UserHelper.php:48 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:57 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:106 +msgid "Logout" +msgstr "Desconectar" + +#: View/Helper/UserHelper.php:123 +msgid "Welcome, {0}" +msgstr "Bem-vindo(a), {0}" + +#: View/Helper/UserHelper.php:146 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"reCaptcha nĆ£o estĆ” configurado! Por favor, configure Users.reCaptcha.key" + +#: View/Helper/UserHelper.php:205 +#, fuzzy +#| msgid "btn btn-social btn-{0} " +msgid "btn btn-social btn-{0}" +msgstr "btn btn-social btn-{0}" + +#: View/Helper/UserHelper.php:211 +msgid "Connected with {0}" +msgstr "Conectador com {0}" + +#: View/Helper/UserHelper.php:216 +msgid "Connect with {0}" +msgstr "Conectar com {0}" + +#~ msgid "Type {0} is not valid" +#~ msgstr "Tipo {0} nĆ£o Ć© vĆ”lido" + +#~ msgid "Type {0} has no associated callable" +#~ msgstr "Tipo {0} nĆ£o tem chamada associada" + +#~ msgid "SSL is required for ApiKey Authentication" +#~ msgstr "SSL Ć© requerido para autenticaĆ§Ć£o por chave da API." + +#~ msgid "" +#~ "Missing configuration file: \"config/{0}.php\". Using default permissions" +#~ msgstr "" +#~ "Arquivo de configuraĆ§Ć£o ausente: \"config/{0}.php\". Usando permissƵes " +#~ "padrĆ£o" + +#~ msgid "" +#~ "Table alias is empty, please define a table alias, we could not extract a " +#~ "default table from the request" +#~ msgstr "" +#~ "O alias da tabela estĆ” vazio, por favor, defina um alias de tabela, nĆ³s " +#~ "nĆ£o pudemos extrair uma tabela padrĆ£o da requisiĆ§Ć£o" + +#~ msgid "" +#~ "Missing column {0} in table {1} while checking ownership permissions for " +#~ "user {2}" +#~ msgstr "" +#~ "Coluna {0} ausente na tabela {1} ao verificar permissƵes de propriedade " +#~ "do usuĆ”rio {2}" + +#~ msgid "" +#~ "If the link is not correcly displayed, please copy the following address " +#~ "in your web browser {0}" +#~ msgstr "" +#~ "Se o link nĆ£o estiver sendo exibido corretamente, por favor, copie o " +#~ "seguinte endereƧo em seu navegador {0}" + +#~ msgid "List Accounts" +#~ msgstr "Listar contas" + +#~ msgid "Related Accounts" +#~ msgstr "Contas relacionadas" + +#~ msgid "User Id" +#~ msgstr "Id de usuĆ”rio" + +#~ msgid "Reference" +#~ msgstr "ReferĆŖncia" + +#~ msgid "Data" +#~ msgstr "Dados" + +#~ msgid "This field is required" +#~ msgstr "Este campo Ć© obrigatĆ³rio" + +#~ msgid "The old password does not match" +#~ msgstr "A senha antiga nĆ£o confere" + +#~ msgid "SocialAccount already active" +#~ msgstr "Conta social jĆ” ativa" + +#~ msgid "" +#~ "The social account is not active. Please check your email for " +#~ "instructions. {0}" +#~ msgstr "" +#~ "A conta social nĆ£o estĆ” ativa. Por favor verifique seu email para " +#~ "instruƧƵes. {0}" + +#~ msgid "There was an error associating your social network account" +#~ msgstr "Houve um erro associando sua conta social" + +#~ msgid "Invalid token and/or email" +#~ msgstr "Token e/ou email invĆ”lido(s)" + +#~ msgid "The \"tos\" property is not present" +#~ msgstr "A propriedade ā€œtosā€ nĆ£o estĆ” presente" + +#~ msgid "+ {0} secs" +#~ msgstr "+ {0} segundos" + +#~ msgid "Sign in with Facebook" +#~ msgstr "Inscrever-se com Facebook" + +#~ msgid "Sign in with Twitter" +#~ msgstr "Inscrever-se com Twitter" diff --git a/src/Locale/sv/Users.mo b/src/Locale/sv/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..746e0c282db28536596d3914137f6af5c3ee11cd GIT binary patch literal 14831 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 G literal 0 HcmV?d00001 diff --git a/src/Locale/sv/Users.po b/src/Locale/sv/Users.po new file mode 100644 index 000000000..839edfdc3 --- /dev/null +++ b/src/Locale/sv/Users.po @@ -0,0 +1,864 @@ +# LANGUAGE translation of CakePHP Application +# Copyright 2010 - 2015, Cake Development Corporation (http://cakedc.com) +# +msgid "" +msgstr "" +"Project-Id-Version: Users\n" +"POT-Creation-Date: 2017-10-25 16:18+0200\n" +"PO-Revision-Date: 2017-10-25 16:24+0200\n" +"Last-Translator: Ulrik Sƶdergren \n" +"Language-Team: CakeDC \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.8.12\n" + +#: Auth/SocialAuthenticate.php:456 +msgid "Provider cannot be empty" +msgstr "Leverantƶr kan inte vara tomt" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Kontot har validerats" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "Konto kunde inte valideras" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "Ogiltig token och/eller social konto" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "Socialt konto redan aktivt" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "Socialt konto kunde inte valideras" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "Epost har skickats." + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "Epost kunde inte skickas" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "Ogiltigt konto" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "E-post kunde inte skickas om" + +#: Controller/Component/RememberMeComponent.php:68 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" +"Ogiltig app salt, mĆ„ste app salt vara Ć„tminstone 256 bitar (32 byte) lĆ„ngt" + +#: Controller/Component/UsersAuthComponent.php:204 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"Du kan inte aktivera epost-validering arbetsflƶde om use_email Ƥr falskt" + +#: Controller/Traits/LinkSocialTrait.php:54 +msgid "Could not associate account, please try again." +msgstr "Kunde inte ansluta konto, fƶrsƶk igen." + +#: Controller/Traits/LinkSocialTrait.php:77 +msgid "Social account was associated." +msgstr "Socialt konto anslƶts." + +#: Controller/Traits/LoginTrait.php:104 +msgid "Issues trying to log in with your social account" +msgstr "Problem vid inloggning med ditt sociala konto" + +#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "LƤgg till din epost" + +#: Controller/Traits/LoginTrait.php:120 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Ditt konto har inte verifierats Ƥnnu. VƤnligen kontrollera din inbox fƶr " +"instruktioner" + +#: Controller/Traits/LoginTrait.php:125 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Ditt sociala konto har inte validerats Ƥnnu. Kontrollera din inkorg fƶr " +"instruktioner" + +#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 +msgid "Invalid reCaptcha" +msgstr "Ogiltig reCaptcha" + +#: Controller/Traits/LoginTrait.php:191 +msgid "You are already logged in" +msgstr "Du Ƥr redan inloggad." + +#: Controller/Traits/LoginTrait.php:212 +msgid "Please enable Google Authenticator first." +msgstr "VƤnligen aktivera Google Authenticator fƶrst." + +#: Controller/Traits/LoginTrait.php:287 +msgid "Verification code is invalid. Try again" +msgstr "Valideringskoden Ƥr ogiltig. Fƶrsƶk igen" + +#: Controller/Traits/LoginTrait.php:340 +msgid "Username or password is incorrect" +msgstr "AnvƤndarnamn eller lƶsenord Ƥr felaktigt" + +#: Controller/Traits/LoginTrait.php:363 +msgid "You've successfully logged out" +msgstr "Du har loggats ut" + +#: Controller/Traits/PasswordManagementTrait.php:49;82 +#: Controller/Traits/ProfileTrait.php:50 +msgid "User was not found" +msgstr "AnvƤndaren hittades inte" + +#: Controller/Traits/PasswordManagementTrait.php:70;78;86 +msgid "Password could not be changed" +msgstr "Lƶsenordet kunde inte Ƥndras" + +#: Controller/Traits/PasswordManagementTrait.php:74 +msgid "Password has been changed successfully" +msgstr "Lƶsenordsbytet lyckades!" + +#: Controller/Traits/PasswordManagementTrait.php:84 +msgid "{0}" +msgstr "{0}" + +#: Controller/Traits/PasswordManagementTrait.php:127 +msgid "Please check your email to continue with password reset process" +msgstr "Kontrollera din epost fƶr att fortsƤtta lƶsenordsĆ„terstƤllningen" + +#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 +msgid "The password token could not be generated. Please try again" +msgstr "Lƶsenordstoken kunde inte skapas. Var god fƶrsƶk igen" + +#: Controller/Traits/PasswordManagementTrait.php:136 +#: Controller/Traits/UserValidationTrait.php:107 +msgid "User {0} was not found" +msgstr "AnvƤndaren {0} hittades inte" + +#: Controller/Traits/PasswordManagementTrait.php:138 +msgid "The user is not active" +msgstr "AnvƤndaren Ƥr inte aktiverad" + +#: Controller/Traits/PasswordManagementTrait.php:140 +#: Controller/Traits/UserValidationTrait.php:102;111 +msgid "Token could not be reset" +msgstr "Token kunde inte Ć„terstƤllas" + +#: Controller/Traits/PasswordManagementTrait.php:164 +msgid "Google Authenticator token was successfully reset" +msgstr "Google Authenticator token har Ć„terstƤllts" + +#: Controller/Traits/ProfileTrait.php:54 +msgid "Not authorized, please login first" +msgstr "Inte auktoriserad, vƤnligen logga in fƶrst" + +#: Controller/Traits/RegisterTrait.php:43 +msgid "You must log out to register a new user account" +msgstr "Du mĆ„ste logga ut fƶr att registrera ett nytt anvƤndarkonto" + +#: Controller/Traits/RegisterTrait.php:89 +msgid "The user could not be saved" +msgstr "AnvƤndaren kunde inte sparas" + +#: Controller/Traits/RegisterTrait.php:123 +msgid "You have registered successfully, please log in" +msgstr "Din registrering Ƥr klar, vƤnligen logga in" + +#: Controller/Traits/RegisterTrait.php:125 +msgid "Please validate your account before log in" +msgstr "VƤnligen validera ditt konto innan inloggning" + +#: Controller/Traits/SimpleCrudTrait.php:77;107 +msgid "The {0} has been saved" +msgstr "{0} har sparats" + +#: Controller/Traits/SimpleCrudTrait.php:81;111 +msgid "The {0} could not be saved" +msgstr "{0} kunde inte sparas" + +#: Controller/Traits/SimpleCrudTrait.php:131 +msgid "The {0} has been deleted" +msgstr "{0} har tagits bort" + +#: Controller/Traits/SimpleCrudTrait.php:133 +msgid "The {0} could not be deleted" +msgstr "{0} kunde inte tas bort" + +#: Controller/Traits/SocialTrait.php:40 +msgid "The reCaptcha could not be validated" +msgstr "reCAPTCHA angavs inte korrekt" + +#: Controller/Traits/UserValidationTrait.php:43 +msgid "User account validated successfully" +msgstr "AnvƤndarkontot har validerats" + +#: Controller/Traits/UserValidationTrait.php:45 +msgid "User account could not be validated" +msgstr "AnvƤndarkontot kunde inte valideras" + +#: Controller/Traits/UserValidationTrait.php:48 +msgid "User already active" +msgstr "AnvƤndaren redan aktiv" + +#: Controller/Traits/UserValidationTrait.php:54 +msgid "Reset password token was validated successfully" +msgstr "ƅterstƤllning av lƶsenord lyckades" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Reset password token could not be validated" +msgstr "Token fƶr att Ć„terstƤlla lƶsenord kunde inte valideras" + +#: Controller/Traits/UserValidationTrait.php:66 +msgid "Invalid validation type" +msgstr "Ogiltig valideringsmetod" + +#: Controller/Traits/UserValidationTrait.php:69 +msgid "Invalid token or user account already validated" +msgstr "Ogiltig token eller sĆ„ har anvƤndaren konto redan validerats" + +#: Controller/Traits/UserValidationTrait.php:71 +msgid "Token already expired" +msgstr "Token redan lƶpt ut" + +#: Controller/Traits/UserValidationTrait.php:97 +msgid "Token has been reset successfully. Please check your email." +msgstr "Token har Ć„terstƤllts. Kontrollera din e-post." + +#: Controller/Traits/UserValidationTrait.php:109 +msgid "User {0} is already active" +msgstr "AnvƤndaren {0} Ƥr redan aktiv" + +#: Mailer/UsersMailer.php:34 +msgid "Your account validation link" +msgstr "Din lƤnk fƶr att validera kontot" + +#: Mailer/UsersMailer.php:52 +msgid "{0}Your reset password link" +msgstr "{0} Din lƤnk fƶr att Ć„terstƤlla lƶsenord" + +#: Mailer/UsersMailer.php:75 +msgid "{0}Your social account validation link" +msgstr "{0} Din sociala konto svalideringslƤnk" + +#: Model/Behavior/AuthFinderBehavior.php:49 +msgid "Missing 'username' in options data" +msgstr "Saknas 'username' i alternativa uppgifter" + +#: Model/Behavior/LinkSocialBehavior.php:53 +msgid "Social account already associated to another user" +msgstr "Socialt konto Ƥr redan kopplat till en annan anvƤndare." + +#: Model/Behavior/PasswordBehavior.php:45 +msgid "Reference cannot be null" +msgstr "Referens fĆ„r inte vara null" + +#: Model/Behavior/PasswordBehavior.php:50 +msgid "Token expiration cannot be empty" +msgstr "Giltighet fƶr token kan inte vara tom" + +#: Model/Behavior/PasswordBehavior.php:56;117 +msgid "User not found" +msgstr "AnvƤndaren hittades inte" + +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112;205 +msgid "User account already validated" +msgstr "Kontot Ƥr redan aktiverat!" + +#: Model/Behavior/PasswordBehavior.php:67 +msgid "User not active" +msgstr "AnvƤndaren ej aktiv" + +#: Model/Behavior/PasswordBehavior.php:122 +msgid "The current password does not match" +msgstr "Den nuvarande lƶsenord matchar inte" + +#: Model/Behavior/PasswordBehavior.php:125 +msgid "You cannot use the current password as the new one" +msgstr "Du kan inte anvƤnda det aktuella lƶsenordet som det nya" + +#: Model/Behavior/RegisterBehavior.php:90 +msgid "User not found for the given token and email." +msgstr "Hittade ingen anvƤndare som matchar angivet token eller epost" + +#: Model/Behavior/RegisterBehavior.php:93 +msgid "Token has already expired user with no token" +msgstr "Token har redan gĆ„tt ut eller anvƤndare utan token" + +#: Model/Behavior/SocialAccountBehavior.php:103;130 +msgid "Account already validated" +msgstr "Kontot Ƥr redan aktiverat!" + +#: Model/Behavior/SocialAccountBehavior.php:106;133 +msgid "Account not found for the given token and email." +msgstr "Kontot hittades inte fƶr givet token och e-post." + +#: Model/Behavior/SocialBehavior.php:82 +msgid "Unable to login user with reference {0}" +msgstr "Det gĆ„r inte att logga in anvƤndaren med refrens {0}" + +#: Model/Behavior/SocialBehavior.php:121 +msgid "Email not present" +msgstr "Epost saknas" + +#: Model/Table/UsersTable.php:81 +msgid "Your password does not match your confirm password. Please try again" +msgstr "Dina lƶsenord matchar inte. VƤnligen fƶrsƶk igen." + +#: Model/Table/UsersTable.php:173 +msgid "Username already exists" +msgstr "AnvƤndarnamnet Ƥr upptaget" + +#: Model/Table/UsersTable.php:179 +msgid "Email already exists" +msgstr "E-postadressen finns redan" + +#: Shell/UsersShell.php:58 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Verktyg fƶr CakeDC User Plugin" + +#: Shell/UsersShell.php:60 +msgid "Activate an specific user" +msgstr "Aktivera en specifik anvƤndare" + +#: Shell/UsersShell.php:63 +msgid "Add a new superadmin user for testing purposes" +msgstr "LƤgga till en ny superadmin anvƤndare fƶr testƤndamĆ„l" + +#: Shell/UsersShell.php:66 +msgid "Add a new user" +msgstr "Ny anvƤndare" + +#: Shell/UsersShell.php:69 +msgid "Change the role for an specific user" +msgstr "Ƅndra rollen fƶr en specifik anvƤndare" + +#: Shell/UsersShell.php:72 +msgid "Deactivate an specific user" +msgstr "Inaktivare en specifik anvƤndare" + +#: Shell/UsersShell.php:75 +msgid "Delete an specific user" +msgstr "Ta bort en specifik anvƤndare" + +#: Shell/UsersShell.php:78 +msgid "Reset the password via email" +msgstr "ƅterstƤll lƶsenord via e-post" + +#: Shell/UsersShell.php:81 +msgid "Reset the password for all users" +msgstr "ƅterstƤll lƶsenord fƶr alla anvƤndare" + +#: Shell/UsersShell.php:84 +msgid "Reset the password for an specific user" +msgstr "ƅterstƤll lƶsenordet fƶr en specifik anvƤndare" + +#: Shell/UsersShell.php:133;159 +msgid "Please enter a password." +msgstr "Ange ett lƶsenord." + +#: Shell/UsersShell.php:137 +msgid "Password changed for all users" +msgstr "Lƶsenordet Ƥndrat fƶr alla anvƤndare" + +#: Shell/UsersShell.php:138;166 +msgid "New password: {0}" +msgstr "Nytt lƶsenord: {0}" + +#: Shell/UsersShell.php:156;184;262;359 +msgid "Please enter a username." +msgstr "Ange ett anvƤndarnamn" + +#: Shell/UsersShell.php:165 +msgid "Password changed for user: {0}" +msgstr "Lƶsenordet Ƥndrat fƶr anvƤndare: {0}" + +#: Shell/UsersShell.php:187 +msgid "Please enter a role." +msgstr "Ange en roll." + +#: Shell/UsersShell.php:193 +msgid "Role changed for user: {0}" +msgstr "Rollen har Ƥndrats fƶr anvƤndare: {0}" + +#: Shell/UsersShell.php:194 +msgid "New role: {0}" +msgstr "Ny roll: {0}" + +#: Shell/UsersShell.php:209 +msgid "User was activated: {0}" +msgstr "AnvƤndaren aktiverades: {0}" + +#: Shell/UsersShell.php:224 +msgid "User was de-activated: {0}" +msgstr "AnvƤndaren avaktiverad: {0}" + +#: Shell/UsersShell.php:236 +msgid "Please enter a username or email." +msgstr "Skriv anvƤndarnamn eller epost" + +#: Shell/UsersShell.php:244 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"Be anvƤndaren kontrollera sin epost fƶr att fortsƤtta " +"lƶsenordsĆ„terstƤllningen" + +#: Shell/UsersShell.php:308 +msgid "Superuser added:" +msgstr "SuperanvƤndare tillagd:" + +#: Shell/UsersShell.php:310 +msgid "User added:" +msgstr "AnvƤndare tillagd:" + +#: Shell/UsersShell.php:312 +msgid "Id: {0}" +msgstr "Id: {0}" + +#: Shell/UsersShell.php:313 +msgid "Username: {0}" +msgstr "AnvƤndarnamn: {0}" + +#: Shell/UsersShell.php:314 +msgid "Email: {0}" +msgstr "Epost: {0}" + +#: Shell/UsersShell.php:315 +msgid "Role: {0}" +msgstr "Roll: {0}" + +#: Shell/UsersShell.php:316 +msgid "Password: {0}" +msgstr "Lƶsenord: {0}" + +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "AnvƤndare kunde inte lƤggas till:" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" +msgstr "FƤlt: {0} fel: {1}" + +#: Shell/UsersShell.php:337 +msgid "The user was not found." +msgstr "AnvƤndaren hittades inte." + +#: Shell/UsersShell.php:367 +msgid "The user {0} was not deleted. Please try again" +msgstr "AnvƤndaren {0} raderades ej. Var god fƶrsƶk igen" + +#: Shell/UsersShell.php:369 +msgid "The user {0} was deleted successfully" +msgstr "AnvƤndaren {0} har tagits bort" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Hej {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "ƅterstƤll ditt lƶsenord hƤr" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Om lƤnken inte visas korrekt, vƤnligen kopiera fƶljande adress till din " +"webblƤsare {0}" + +#: Template/Email/html/reset_password.ctp:34 +#: Template/Email/html/social_account_validation.ctp:39 +#: Template/Email/html/validation.ctp:34 +#: Template/Email/text/reset_password.ctp:28 +#: Template/Email/text/social_account_validation.ctp:30 +#: Template/Email/text/validation.ctp:28 +msgid "Thank you" +msgstr "Tack" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Aktivera ditt sociala konto hƤr" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Aktivera ditt konto hƤr" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "Kopiera fƶljande adress till webblƤsaren {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"Kopiera fƶljande adress till din webblƤsare fƶr att aktivera din sociala " +"inloggning {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 +msgid "Actions" +msgstr "Resurser" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:23 +msgid "List Users" +msgstr "Lista anvƤndare" + +#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 +msgid "Add User" +msgstr "Ny anvƤndare" + +#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 +msgid "Username" +msgstr "AnvƤndarnamn" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 +msgid "Email" +msgstr "Epost" + +#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 +msgid "Password" +msgstr "Lƶsenord" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 +msgid "First name" +msgstr "Fƶrnamn" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 +msgid "Last name" +msgstr "Efternamn" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:49;74 +msgid "Active" +msgstr "Aktivt" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Skicka" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Ange ditt nya lƶsenord" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Nuvarande lƶsenord" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Nytt lƶsenord" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 +msgid "Confirm password" +msgstr "BekrƤfta lƶsenord" + +#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 +msgid "Delete" +msgstr "Radera" + +#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:21 +msgid "Are you sure you want to delete # {0}?" +msgstr "Ƅr du sƤker pĆ„ att du vill radera{0}" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Redigera anvƤndare" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 +msgid "Token" +msgstr "Token" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Token fƶrfaller" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "API-token" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Aktiveringsdatum" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "TOS datum" + +#: Template/Users/edit.ctp:63 +msgid "Reset Google Authenticator Token" +msgstr "ƅterstƤll Google Authenticator Token" + +#: Template/Users/edit.ctp:69 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "Ƅr du sƤker du vill Ć„terstƤlla token fƶr anvƤndare \"{0}\"?" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Nytt {0}" + +#: Template/Users/index.ctp:37 +msgid "View" +msgstr "Visa" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Byt lƶsenord" + +#: Template/Users/index.ctp:39 +msgid "Edit" +msgstr "Ƅndra" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "fƶregĆ„ende" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "nƤsta" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Ange ditt anvƤndarnamn och lƶsenord" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "Kom ihĆ„g mig" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Registrera" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "ƅterstƤll Lƶsenord" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "Logga in" + +#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:27 +msgid "Change Password" +msgstr "Ƅndra Lƶsenord" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 +msgid "Social Accounts" +msgstr "Sociala konton" + +#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 +msgid "Avatar" +msgstr "Profilbild" + +#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 +msgid "Provider" +msgstr "Utfƶrare" + +#: Template/Users/profile.ctp:44 +msgid "Link" +msgstr "LƤnk" + +#: Template/Users/profile.ctp:51 +msgid "Link to {0}" +msgstr "LƤnk till {0}" + +#: Template/Users/register.ctp:29 +msgid "Accept TOS conditions?" +msgstr "Jag accepterar villkoren" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Ange din e-postadress fƶr att Ć„terstƤlla ditt lƶsenord" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Skicka nytt bekrƤftelsemejl" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "E-post/AnvƤndarnamn" + +#: Template/Users/verify.ctp:13 +msgid "Verification Code" +msgstr "Verifieringskod" + +#: Template/Users/verify.ctp:15 +msgid "" +" " +"Verify" +msgstr "" +" " +"Verifiera" + +#: Template/Users/view.ctp:19 +msgid "Delete User" +msgstr "Ta bort anvƤndare" + +#: Template/Users/view.ctp:24 +msgid "New User" +msgstr "Ny anvƤndare" + +#: Template/Users/view.ctp:31 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:37 +msgid "First Name" +msgstr "Fƶrnamn" + +#: Template/Users/view.ctp:39 +msgid "Last Name" +msgstr "Efternamn" + +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "Roll" + +#: Template/Users/view.ctp:45 +msgid "Api Token" +msgstr "Api-token" + +#: Template/Users/view.ctp:53 +msgid "Token Expires" +msgstr "Token fƶrfaller" + +#: Template/Users/view.ctp:55 +msgid "Activation Date" +msgstr "Aktiveringsdatum" + +#: Template/Users/view.ctp:57 +msgid "Tos Date" +msgstr "Tos datum" + +#: Template/Users/view.ctp:59;75 +msgid "Created" +msgstr "Skapad" + +#: Template/Users/view.ctp:61;76 +msgid "Modified" +msgstr "Ƅndrad" + +#: View/Helper/UserHelper.php:45 +msgid "Sign in with" +msgstr "Logga in med" + +#: View/Helper/UserHelper.php:48 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:57 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:106 +msgid "Logout" +msgstr "Logga ut" + +#: View/Helper/UserHelper.php:123 +msgid "Welcome, {0}" +msgstr "VƤlkommen, {0}" + +#: View/Helper/UserHelper.php:146 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "reCaptcha Ƥr inte konfigurerad! Konfigurera Users.reCaptcha.key" + +#: View/Helper/UserHelper.php:205 +msgid "btn btn-social btn-{0}" +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:211 +msgid "Connected with {0}" +msgstr "Ansluten med {0}" + +#: View/Helper/UserHelper.php:216 +msgid "Connect with {0}" +msgstr "Anslut med {0}" + +#~ msgid "Type {0} is not valid" +#~ msgstr "Typ {0} Ƥr inte giltig" + +#~ msgid "Type {0} has no associated callable" +#~ msgstr "Typ {0} har inget tillhƶrande anrop" + +#~ msgid "SSL is required for ApiKey Authentication" +#~ msgstr "SSL krƤvs fƶr ApiKey-autentisering" + +#~ msgid "" +#~ "Missing configuration file: \"config/{0}.php\". Using default permissions" +#~ msgstr "" +#~ "Saknad konfigurationsfil: \"config / {0} .php\". AnvƤnder " +#~ "standardbehƶrigheter" + +#~ msgid "" +#~ "Table alias is empty, please define a table alias, we could not extract a " +#~ "default table from the request" +#~ msgstr "" +#~ "Tabellalias Ƥr tomt, var vƤnlig ange ett tabellalias, vi kunde inte " +#~ "extrahera nĆ„gon standardtabell" + +#~ msgid "" +#~ "Missing column {0} in table {1} while checking ownership permissions for " +#~ "user {2}" +#~ msgstr "" +#~ "Saknar kolumn {0} i tabell {1} vid kontroll av Ƥgarbehƶrigheter fƶr " +#~ "anvƤndare {2}" + +#~ msgid "List Accounts" +#~ msgstr "Lista konton" + +#~ msgid "Related Accounts" +#~ msgstr "Relaterade konton" + +#~ msgid "User Id" +#~ msgstr "AnvƤndar-ID" + +#~ msgid "Reference" +#~ msgstr "Referens" + +#~ msgid "Data" +#~ msgstr "Data" + +#~ msgid "This field is required" +#~ msgstr "Detta fƤlt Ƥr obligatoriskt" diff --git a/src/Locale/tr_TR/Users.mo b/src/Locale/tr_TR/Users.mo new file mode 100644 index 0000000000000000000000000000000000000000..c65ebec0d2712a5e0117fa2b0d3ae8d036658bdf GIT binary patch literal 15267 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 t5bsklw +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2017-10-14 23:45+0000\n" +"PO-Revision-Date: 2018-01-22 22:21+0300\n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.0.6\n" +"Last-Translator: \n" +"Language: tr_TR\n" + +#: Auth/SocialAuthenticate.php:456 +msgid "Provider cannot be empty" +msgstr "Sağlayıcı boş olamaz" + +#: Controller/SocialAccountsController.php:52 +msgid "Account validated successfully" +msgstr "Hesap başarıyla doğrulandı" + +#: Controller/SocialAccountsController.php:54 +msgid "Account could not be validated" +msgstr "Hesap doğrulanamadı" + +#: Controller/SocialAccountsController.php:57 +msgid "Invalid token and/or social account" +msgstr "GeƧersiz jeton ve/veya sosyal hesap" + +#: Controller/SocialAccountsController.php:59;87 +msgid "Social Account already active" +msgstr "Sosyal Hesap zaten aktif" + +#: Controller/SocialAccountsController.php:61 +msgid "Social Account could not be validated" +msgstr "Sosyal Hesap doğrulanamadı" + +#: Controller/SocialAccountsController.php:80 +msgid "Email sent successfully" +msgstr "E-posta başarıyla gƶnderildi" + +#: Controller/SocialAccountsController.php:82 +msgid "Email could not be sent" +msgstr "E-posta gƶnderilemedi" + +#: Controller/SocialAccountsController.php:85 +msgid "Invalid account" +msgstr "GeƧersiz hesap" + +#: Controller/SocialAccountsController.php:89 +msgid "Email could not be resent" +msgstr "E-posta tekrar gƶnderilemedi" + +#: Controller/Component/RememberMeComponent.php:68 +msgid "Invalid app salt, app salt must be at least 256 bits (32 bytes) long" +msgstr "" +"GeƧersiz tuz kodu, tuz kodu en az 256 bit (32 bayt) ā€œlongā€ uzunluğunda olmalı" + +#: Controller/Component/UsersAuthComponent.php:204 +msgid "You can't enable email validation workflow if use_email is false" +msgstr "" +"Eğer use_email yanlışsa, e-posta doğrulama iş akışını etkinleştiremezsin" + +#: Controller/Traits/LinkSocialTrait.php:54 +msgid "Could not associate account, please try again." +msgstr "Hesap eşleştirilemedi, lĆ¼tfen tekrar deneyin." + +#: Controller/Traits/LinkSocialTrait.php:77 +msgid "Social account was associated." +msgstr "Sosyal hesap zaten eşleştirilmişti." + +#: Controller/Traits/LoginTrait.php:104 +msgid "Issues trying to log in with your social account" +msgstr "Sosyal hesabınız ile giriş yaparken Ƨıkan sorunlar" + +#: Controller/Traits/LoginTrait.php:109 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "LĆ¼tfen e-posta hesabınızı girin" + +#: Controller/Traits/LoginTrait.php:120 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Kullanıcınız henĆ¼z doğrulanmadı. LĆ¼tfen talimatlar iƧin gelen kutunuzu " +"kontrol edin" + +#: Controller/Traits/LoginTrait.php:125 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Sosyal hesabınız henĆ¼z doğrulanmadı. LĆ¼tfen talimatlar iƧin gelen kutunuzu " +"kontrol edin" + +#: Controller/Traits/LoginTrait.php:180 Controller/Traits/RegisterTrait.php:82 +msgid "Invalid reCaptcha" +msgstr "GeƧersiz reCaptcha" + +#: Controller/Traits/LoginTrait.php:191 +msgid "You are already logged in" +msgstr "Zaten giriş yapmış durumdasınız" + +#: Controller/Traits/LoginTrait.php:212 +msgid "Please enable Google Authenticator first." +msgstr "LĆ¼tfen ƶnce Google Authenticator ā€˜Ä± aktif hale getirin." + +#: Controller/Traits/LoginTrait.php:287 +msgid "Verification code is invalid. Try again" +msgstr "Doğrulama kodu yanlış. Tekrar deneyin" + +#: Controller/Traits/LoginTrait.php:340 +msgid "Username or password is incorrect" +msgstr "Kullanıcı adınız veya şifreniz yanlış" + +#: Controller/Traits/LoginTrait.php:363 +msgid "You've successfully logged out" +msgstr "Başarıyla Ƨıkış yaptınız" + +#: Controller/Traits/PasswordManagementTrait.php:49;82 +#: Controller/Traits/ProfileTrait.php:50 +msgid "User was not found" +msgstr "Kullanıcı bulunamadı" + +#: Controller/Traits/PasswordManagementTrait.php:70;78;86 +msgid "Password could not be changed" +msgstr "Şifre değiştirilemedi" + +#: Controller/Traits/PasswordManagementTrait.php:74 +msgid "Password has been changed successfully" +msgstr "Şifre başarıyla değiştirildi" + +#: Controller/Traits/PasswordManagementTrait.php:84 +msgid "{0}" +msgstr "{0}" + +#: Controller/Traits/PasswordManagementTrait.php:127 +msgid "Please check your email to continue with password reset process" +msgstr "" +"Şifre sıfırlama işleminize devam edebilmek iƧin lĆ¼tfen e-postanızı kontrol " +"edin" + +#: Controller/Traits/PasswordManagementTrait.php:130 Shell/UsersShell.php:247 +msgid "The password token could not be generated. Please try again" +msgstr "Şifre jetonu oluşturulamadı. LĆ¼tfen tekrar deneyin" + +#: Controller/Traits/PasswordManagementTrait.php:136 +#: Controller/Traits/UserValidationTrait.php:107 +msgid "User {0} was not found" +msgstr "Kullancı {0} bulunamadı" + +#: Controller/Traits/PasswordManagementTrait.php:138 +msgid "The user is not active" +msgstr "Kullanıcı aktif değil" + +#: Controller/Traits/PasswordManagementTrait.php:140 +#: Controller/Traits/UserValidationTrait.php:102;111 +msgid "Token could not be reset" +msgstr "Jeton sıfırlanamadı" + +#: Controller/Traits/PasswordManagementTrait.php:164 +msgid "Google Authenticator token was successfully reset" +msgstr "Google Authenticator jetonu başarıyla sıfırlandı" + +#: Controller/Traits/ProfileTrait.php:54 +msgid "Not authorized, please login first" +msgstr "Yetkili değil, lĆ¼tfen ilk ƶnce giriş yapın" + +#: Controller/Traits/RegisterTrait.php:43 +msgid "You must log out to register a new user account" +msgstr "Yeni bir hesap oluşturmak oluşturmak iƧin ƶnce Ƨıkış yapmanız gerekli" + +#: Controller/Traits/RegisterTrait.php:89 +msgid "The user could not be saved" +msgstr "Kullanıcı kaydedilemedi" + +#: Controller/Traits/RegisterTrait.php:123 +msgid "You have registered successfully, please log in" +msgstr "Başarıyla kayıt oldunuz, lĆ¼tfen giriş yapın" + +#: Controller/Traits/RegisterTrait.php:125 +msgid "Please validate your account before log in" +msgstr "LĆ¼tfen giriş yapmadan ƶnce hesabınızı doğrulayın" + +#: Controller/Traits/SimpleCrudTrait.php:77;107 +msgid "The {0} has been saved" +msgstr "{0} kaydedildi" + +#: Controller/Traits/SimpleCrudTrait.php:81;111 +msgid "The {0} could not be saved" +msgstr "{0} kaydedilemedi" + +#: Controller/Traits/SimpleCrudTrait.php:131 +msgid "The {0} has been deleted" +msgstr "{0} silindi" + +#: Controller/Traits/SimpleCrudTrait.php:133 +msgid "The {0} could not be deleted" +msgstr "{0} silinemedi" + +#: Controller/Traits/SocialTrait.php:40 +msgid "The reCaptcha could not be validated" +msgstr "reCaptcha doğrulanamadı" + +#: Controller/Traits/UserValidationTrait.php:43 +msgid "User account validated successfully" +msgstr "Kullanıcı hesabı başarıyla doğrulandı" + +#: Controller/Traits/UserValidationTrait.php:45 +msgid "User account could not be validated" +msgstr "Kullanıcı hesabı doğrulanamadı" + +#: Controller/Traits/UserValidationTrait.php:48 +msgid "User already active" +msgstr "Kullanıcı zaten aktif" + +#: Controller/Traits/UserValidationTrait.php:54 +msgid "Reset password token was validated successfully" +msgstr "Şifre sıfırlama jetonu başarıyla doğrulandı" + +#: Controller/Traits/UserValidationTrait.php:62 +msgid "Reset password token could not be validated" +msgstr "Şifre sıfırlama jetonu doğrulanamadı" + +#: Controller/Traits/UserValidationTrait.php:66 +msgid "Invalid validation type" +msgstr "GeƧersiz doğrulama cinsi" + +#: Controller/Traits/UserValidationTrait.php:69 +msgid "Invalid token or user account already validated" +msgstr "GeƧersiz jeton veya kullanıcı hesabı zaten doğrulandı" + +#: Controller/Traits/UserValidationTrait.php:71 +msgid "Token already expired" +msgstr "Jeton sĆ¼resi zaten doldu" + +#: Controller/Traits/UserValidationTrait.php:97 +msgid "Token has been reset successfully. Please check your email." +msgstr "Jeton başarıyla sıfırlandı. LĆ¼tfen e-postanızı kontrol edin." + +#: Controller/Traits/UserValidationTrait.php:109 +msgid "User {0} is already active" +msgstr "Kullanıcı {0} zaten aktif" + +#: Mailer/UsersMailer.php:34 +msgid "Your account validation link" +msgstr "Hesap doğrulama bağlantısı" + +#: Mailer/UsersMailer.php:52 +msgid "{0}Your reset password link" +msgstr "{0} Şifre sıfırlama bağlantısı" + +#: Mailer/UsersMailer.php:75 +msgid "{0}Your social account validation link" +msgstr "{0} Sosyal hesap doğrulama bağlantısı" + +#: Model/Behavior/AuthFinderBehavior.php:49 +msgid "Missing 'username' in options data" +msgstr "SeƧenekler verilerinde ā€˜kullanıcı adıā€™ eksik" + +#: Model/Behavior/LinkSocialBehavior.php:53 +msgid "Social account already associated to another user" +msgstr "Sosyal hesap zaten başka bir kullanıcıyla eşleşmiş durumda" + +#: Model/Behavior/PasswordBehavior.php:45 +msgid "Reference cannot be null" +msgstr "Referans boş olamaz" + +#: Model/Behavior/PasswordBehavior.php:50 +msgid "Token expiration cannot be empty" +msgstr "Jeton son kullanma tarihi boş olamaz" + +#: Model/Behavior/PasswordBehavior.php:56;117 +msgid "User not found" +msgstr "Kullanıcı bulunamadı" + +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112;205 +msgid "User account already validated" +msgstr "Kullanıcı hesabı zaten doğrulandı" + +#: Model/Behavior/PasswordBehavior.php:67 +msgid "User not active" +msgstr "Kullanıcı aktif durumda değil" + +#: Model/Behavior/PasswordBehavior.php:122 +msgid "The current password does not match" +msgstr "GeƧerli şifre uyuşmuyor" + +#: Model/Behavior/PasswordBehavior.php:125 +msgid "You cannot use the current password as the new one" +msgstr "GeƧerli şifrenizi yeni bir şifre olarak kullanamazsınız" + +#: Model/Behavior/RegisterBehavior.php:90 +msgid "User not found for the given token and email." +msgstr "Verilen jeton ve e-posta iƧin kullanıcı bulunamadı." + +#: Model/Behavior/RegisterBehavior.php:93 +msgid "Token has already expired user with no token" +msgstr "Jeton son kullanma tarihi zaten doldu, kullanıcının jetonu yok" + +#: Model/Behavior/SocialAccountBehavior.php:103;130 +msgid "Account already validated" +msgstr "Hesap zaten doğrulandı" + +#: Model/Behavior/SocialAccountBehavior.php:106;133 +msgid "Account not found for the given token and email." +msgstr "Verilen jeton ve e-posta iƧin hesap bulunamadı." + +#: Model/Behavior/SocialBehavior.php:82 +msgid "Unable to login user with reference {0}" +msgstr "Referans {0} ile giriş başarısız" + +#: Model/Behavior/SocialBehavior.php:121 +msgid "Email not present" +msgstr "E-posta yok" + +#: Model/Table/UsersTable.php:81 +msgid "Your password does not match your confirm password. Please try again" +msgstr "Şifreniz onay şifreniz ile uyuşmuyor. LĆ¼tfen tekrar deneyin" + +#: Model/Table/UsersTable.php:173 +msgid "Username already exists" +msgstr "Kullanıcı adı zaten var" + +#: Model/Table/UsersTable.php:179 +msgid "Email already exists" +msgstr "E-posta zaten var" + +#: Shell/UsersShell.php:58 +msgid "Utilities for CakeDC Users Plugin" +msgstr "CakeDC Users eklentisi iƧin araƧlar" + +#: Shell/UsersShell.php:60 +msgid "Activate an specific user" +msgstr "Belirli bir kullanıcıyı aktif hale getir" + +#: Shell/UsersShell.php:63 +msgid "Add a new superadmin user for testing purposes" +msgstr "Deneme iƧin yeni bir sĆ¼peryƶnetici kullanıcısı ekle" + +#: Shell/UsersShell.php:66 +msgid "Add a new user" +msgstr "Yeni bir kullanıcı ekle" + +#: Shell/UsersShell.php:69 +msgid "Change the role for an specific user" +msgstr "Belirli bir kullanıcının rolĆ¼nĆ¼ değiştir" + +#: Shell/UsersShell.php:72 +msgid "Deactivate an specific user" +msgstr "Belirli bir kullanıcıyı devre dışı bırak" + +#: Shell/UsersShell.php:75 +msgid "Delete an specific user" +msgstr "Belirli bir kullanıcıyı sil" + +#: Shell/UsersShell.php:78 +msgid "Reset the password via email" +msgstr "Şifreyi e-posta aracılığıyla sıfırla" + +#: Shell/UsersShell.php:81 +msgid "Reset the password for all users" +msgstr "TĆ¼m kullanıcıların şifrelerini sıfırla" + +#: Shell/UsersShell.php:84 +msgid "Reset the password for an specific user" +msgstr "Belirli bir kullanıcının şifresini sıfırla" + +#: Shell/UsersShell.php:133;159 +msgid "Please enter a password." +msgstr "LĆ¼tfen bir şifre gir." + +#: Shell/UsersShell.php:137 +msgid "Password changed for all users" +msgstr "TĆ¼m kullanıcıların şifreleri değiştirildi" + +#: Shell/UsersShell.php:138;166 +msgid "New password: {0}" +msgstr "Yeni şifre: {0}" + +#: Shell/UsersShell.php:156;184;262;359 +msgid "Please enter a username." +msgstr "LĆ¼tfen bir kullanıcı adı gir." + +#: Shell/UsersShell.php:165 +msgid "Password changed for user: {0}" +msgstr "Kullanıcı iƧin şifre değiştirildi: {0}" + +#: Shell/UsersShell.php:187 +msgid "Please enter a role." +msgstr "LĆ¼tfen bir rol gir." + +#: Shell/UsersShell.php:193 +msgid "Role changed for user: {0}" +msgstr "Kullanıcı rolĆ¼ değiştirildi: {0}" + +#: Shell/UsersShell.php:194 +msgid "New role: {0}" +msgstr "Yeni rol: {0}" + +#: Shell/UsersShell.php:209 +msgid "User was activated: {0}" +msgstr "Kullanıcı aktif hale getirildi: {0}" + +#: Shell/UsersShell.php:224 +msgid "User was de-activated: {0}" +msgstr "Kullanıcı devre dışı bırakıldı: {0}" + +#: Shell/UsersShell.php:236 +msgid "Please enter a username or email." +msgstr "LĆ¼tfen kullanıcı adı veya e-posta girin." + +#: Shell/UsersShell.php:244 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"Şifre sıfırlama işlemine devam etmek iƧin, lĆ¼tfen kullanıcıya e-posta " +"hesabını kontrol etmesini sƶyleyin" + +#: Shell/UsersShell.php:308 +msgid "Superuser added:" +msgstr "SĆ¼perkullanıcı eklendi:" + +#: Shell/UsersShell.php:310 +msgid "User added:" +msgstr "Kullanıcı eklendi:" + +#: Shell/UsersShell.php:312 +msgid "Id: {0}" +msgstr "Id: {0}" + +#: Shell/UsersShell.php:313 +msgid "Username: {0}" +msgstr "Kullanıcı Adı: {0}" + +#: Shell/UsersShell.php:314 +msgid "Email: {0}" +msgstr "E-posta: {0}" + +#: Shell/UsersShell.php:315 +msgid "Role: {0}" +msgstr "Rol: {0}" + +#: Shell/UsersShell.php:316 +msgid "Password: {0}" +msgstr "Şifre: {0}" + +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "Kullanıcı eklenemedi:" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" +msgstr "Alan: {0} Hata: {1}" + +#: Shell/UsersShell.php:337 +msgid "The user was not found." +msgstr "Kullanıcı bulunamadı." + +#: Shell/UsersShell.php:367 +msgid "The user {0} was not deleted. Please try again" +msgstr "Kullanıcı {0} silinemedi. LĆ¼tfen tekrar deneyin" + +#: Shell/UsersShell.php:369 +msgid "The user {0} was deleted successfully" +msgstr "Kullanıcı {0} başarıyla silindi" + +#: Template/Email/html/reset_password.ctp:21 +#: Template/Email/html/social_account_validation.ctp:14 +#: Template/Email/html/validation.ctp:21 +#: Template/Email/text/reset_password.ctp:20 +#: Template/Email/text/social_account_validation.ctp:22 +#: Template/Email/text/validation.ctp:20 +msgid "Hi {0}" +msgstr "Merhaba {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Şifrenizi buradan sıfırlayın" + +#: Template/Email/html/reset_password.ctp:27 +#: Template/Email/html/social_account_validation.ctp:32 +#: Template/Email/html/validation.ctp:27 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" +msgstr "" +"Eğer bağlantı dĆ¼zgĆ¼n şekilde gƶzĆ¼kmĆ¼yorsa, lĆ¼tfen adresi internet tarayıcına " +"kopyala {0}" + +#: Template/Email/html/reset_password.ctp:34 +#: Template/Email/html/social_account_validation.ctp:39 +#: Template/Email/html/validation.ctp:34 +#: Template/Email/text/reset_password.ctp:28 +#: Template/Email/text/social_account_validation.ctp:30 +#: Template/Email/text/validation.ctp:28 +msgid "Thank you" +msgstr "TeşekkĆ¼rler" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Sosyal girişi buradan aktif hale getirin" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Hesabınızı buradan aktif hale getirin" + +#: Template/Email/text/reset_password.ctp:22 +#: Template/Email/text/validation.ctp:22 +msgid "Please copy the following address in your web browser {0}" +msgstr "LĆ¼tfen adresi internet tarayıcınıza kopyalayın {0}" + +#: Template/Email/text/social_account_validation.ctp:24 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"LĆ¼tfen sosyal girişi aktif hale getirmek iƧin adresi internet tarayıcınıza " +"kopyalayın {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:16 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 +msgid "Actions" +msgstr "Aksiyonlar" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:27 +#: Template/Users/view.ctp:23 +msgid "List Users" +msgstr "Kullanıcıları Listele" + +#: Template/Users/add.ctp:21 Template/Users/register.ctp:17 +msgid "Add User" +msgstr "Kullanıcı Ekle" + +#: Template/Users/add.ctp:23 Template/Users/edit.ctp:35 +#: Template/Users/index.ctp:22 Template/Users/profile.ctp:30 +#: Template/Users/register.ctp:19 Template/Users/view.ctp:33 +msgid "Username" +msgstr "Kullanıcı Adı" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:20 Template/Users/view.ctp:35 +msgid "Email" +msgstr "E-posta" + +#: Template/Users/add.ctp:25 Template/Users/register.ctp:21 +msgid "Password" +msgstr "Şifre" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:26 +msgid "First name" +msgstr "Ad" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:27 +msgid "Last name" +msgstr "Soyad" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:53 +#: Template/Users/view.ctp:49;74 +msgid "Active" +msgstr "Aktif" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:57 Template/Users/register.ctp:36 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Gƶnder" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "LĆ¼tfen yeni bir şifre gir" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "GeƧerli şifre" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Yeni şifre" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:24 +msgid "Confirm password" +msgstr "Şifre onayla" + +#: Template/Users/edit.ctp:21 Template/Users/index.ctp:40 +msgid "Delete" +msgstr "Sil" + +#: Template/Users/edit.ctp:23 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:21 +msgid "Are you sure you want to delete # {0}?" +msgstr "Silmek istediğine emin misin # {0}?" + +#: Template/Users/edit.ctp:33 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Kullanıcıyı dĆ¼zenle" + +#: Template/Users/edit.ctp:39 Template/Users/view.ctp:43 +msgid "Token" +msgstr "Jeton" + +#: Template/Users/edit.ctp:41 +msgid "Token expires" +msgstr "Jeton Son Kullanma Tarihi" + +#: Template/Users/edit.ctp:44 +msgid "API token" +msgstr "API jetonu" + +#: Template/Users/edit.ctp:47 +msgid "Activation date" +msgstr "Aktivasyon tarihi" + +#: Template/Users/edit.ctp:50 +msgid "TOS date" +msgstr "TOS tarihi" + +#: Template/Users/edit.ctp:63 +msgid "Reset Google Authenticator Token" +msgstr "Google Authenticator Jetonunu Sıfırla" + +#: Template/Users/edit.ctp:69 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "Kullanıcı {0} iƧin jetonu sıfırlamak istediğine emin misin?" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Yeni {0}" + +#: Template/Users/index.ctp:37 +msgid "View" +msgstr "GƶrĆ¼nĆ¼m" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Şifre değiştir" + +#: Template/Users/index.ctp:39 +msgid "Edit" +msgstr "DĆ¼zenle" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "ƶnceki" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "sonraki" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "LĆ¼tfen kullanıcı adını ve şifreni gir" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "Beni Hatırla" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Kayıt Ol" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Şifre Sıfırla" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "Giriş" + +#: Template/Users/profile.ctp:21 View/Helper/UserHelper.php:54 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:27 +msgid "Change Password" +msgstr "Şifre Değiştir" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 +msgid "Social Accounts" +msgstr "Sosyal Hesaplar" + +#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 +msgid "Avatar" +msgstr "Avatar" + +#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 +msgid "Provider" +msgstr "Sağlayıcı" + +#: Template/Users/profile.ctp:44 +msgid "Link" +msgstr "Bağlantı" + +#: Template/Users/profile.ctp:51 +msgid "Link to {0}" +msgstr "Şuna bağlı {0}" + +#: Template/Users/register.ctp:29 +msgid "Accept TOS conditions?" +msgstr "TOS koşullarını kabul ediyor musun?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Şifreni sıfırlamak iƧin lĆ¼tfen e-postanı gir" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Doğrulama e-postasını yeniden gƶnder" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "E-posta veta kullanıcı adı" + +#: Template/Users/verify.ctp:13 +msgid "Verification Code" +msgstr "Doğrulama Kodu" + +#: Template/Users/verify.ctp:15 +msgid "" +" " +"Verify" +msgstr "" +" Verify" + +#: Template/Users/view.ctp:19 +msgid "Delete User" +msgstr "Kullanıcıyı Sil" + +#: Template/Users/view.ctp:24 +msgid "New User" +msgstr "Yeni Kullanıcı" + +#: Template/Users/view.ctp:31 +msgid "Id" +msgstr "Id" + +#: Template/Users/view.ctp:37 +msgid "First Name" +msgstr "Ad" + +#: Template/Users/view.ctp:39 +msgid "Last Name" +msgstr "Soyad" + +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "Rol" + +#: Template/Users/view.ctp:45 +msgid "Api Token" +msgstr "Api Jeton" + +#: Template/Users/view.ctp:53 +msgid "Token Expires" +msgstr "Jeton Bitiş Tarihi" + +#: Template/Users/view.ctp:55 +msgid "Activation Date" +msgstr "Aktivasyon Tarihi" + +#: Template/Users/view.ctp:57 +msgid "Tos Date" +msgstr "Tos Tarihi" + +#: Template/Users/view.ctp:59;75 +msgid "Created" +msgstr "Oluşturulmuş" + +#: Template/Users/view.ctp:61;76 +msgid "Modified" +msgstr "Değiştirilmiş" + +#: View/Helper/UserHelper.php:45 +msgid "Sign in with" +msgstr "Şununla giriş yapın" + +#: View/Helper/UserHelper.php:48 +msgid "fa fa-{0}" +msgstr "fa fa-{0}" + +#: View/Helper/UserHelper.php:57 +msgid "btn btn-social btn-{0} " +msgstr "btn btn-social btn-{0} " + +#: View/Helper/UserHelper.php:106 +msgid "Logout" +msgstr "Ƈıkış" + +#: View/Helper/UserHelper.php:123 +msgid "Welcome, {0}" +msgstr "Hoşgeldiniz, {0}" + +#: View/Helper/UserHelper.php:146 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"reCaptcha konfigĆ¼re edilmedi! LĆ¼tfen konfigĆ¼re edin Users.reCaptcha.key" + +#: View/Helper/UserHelper.php:205 +msgid "btn btn-social btn-{0}" +msgstr "btn btn-social btn-{0}" + +#: View/Helper/UserHelper.php:211 +msgid "Connected with {0}" +msgstr "Şununla bağlanıldı {0}" + +#: View/Helper/UserHelper.php:216 +msgid "Connect with {0}" +msgstr "Şununla bağlan {0}" diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php new file mode 100644 index 000000000..2e021884d --- /dev/null +++ b/src/Mailer/UsersMailer.php @@ -0,0 +1,81 @@ +setHidden(['password', 'token_expires', 'api_token']); + $subject = __d('CakeDC/Users', 'Your account validation link'); + $this + ->setTo($user['email']) + ->setSubject($firstName . $subject) + ->setViewVars($user->toArray()) + ->setTemplate('CakeDC/Users.validation'); + } + + /** + * Send the reset password email to the user + * + * @param EntityInterface $user User entity + * + * @return void + */ + protected function resetPassword(EntityInterface $user) + { + $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + $subject = __d('CakeDC/Users', '{0}Your reset password link', $firstName); + // un-hide the token to be able to send it in the email content + $user->setHidden(['password', 'token_expires', 'api_token']); + + $this + ->setTo($user['email']) + ->setSubject($subject) + ->setViewVars($user->toArray()) + ->setTemplate('CakeDC/Users.resetPassword'); + } + + /** + * Send account validation email to the user + * + * @param EntityInterface $user User entity + * @param EntityInterface $socialAccount SocialAccount entity + * + * @return void + */ + protected function socialAccountValidation(EntityInterface $user, EntityInterface $socialAccount) + { + $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; + // note: we control the space after the username in the previous line + $subject = __d('CakeDC/Users', '{0}Your social account validation link', $firstName); + $this + ->setTo($user['email']) + ->setSubject($subject) + ->setViewVars(compact('user', 'socialAccount')) + ->setTemplate('CakeDC/Users.socialAccountValidation'); + } +} diff --git a/src/Model/Behavior/AuthFinderBehavior.php b/src/Model/Behavior/AuthFinderBehavior.php new file mode 100644 index 000000000..ef51d1fc9 --- /dev/null +++ b/src/Model/Behavior/AuthFinderBehavior.php @@ -0,0 +1,62 @@ +where([$this->_table->aliasField('active') => 1]); + + return $query; + } + + /** + * Custom finder to log in users + * + * @param Query $query Query object to modify + * @param array $options Query options + * @return Query + * @throws \BadMethodCallException + */ + public function findAuth(Query $query, array $options = []) + { + $identifier = Hash::get($options, 'username'); + if (empty($identifier)) { + throw new \BadMethodCallException(__d('CakeDC/Users', 'Missing \'username\' in options data')); + } + $where = $query->clause('where') ?: []; + $query + ->where(function ($exp) use ($identifier, $where) { + $or = $exp->or_([$this->_table->aliasField('email') => $identifier]); + + return $or->add($where); + }, [], true) + ->find('active', $options); + + return $query; + } +} diff --git a/src/Model/Behavior/BaseTokenBehavior.php b/src/Model/Behavior/BaseTokenBehavior.php new file mode 100644 index 000000000..1e6207159 --- /dev/null +++ b/src/Model/Behavior/BaseTokenBehavior.php @@ -0,0 +1,59 @@ +updateToken($tokenExpiration); + } else { + $user['active'] = true; + $user['activation_date'] = new Time(); + } + + return $user; + } + + /** + * Remove user token for validation + * + * @param EntityInterface $user user object. + * @return EntityInterface + */ + protected function _removeValidationToken(EntityInterface $user) + { + $user->token = null; + $user->token_expires = null; + $result = $this->_table->save($user); + + return $result; + } +} diff --git a/src/Model/Behavior/LinkSocialBehavior.php b/src/Model/Behavior/LinkSocialBehavior.php new file mode 100644 index 000000000..68f48608c --- /dev/null +++ b/src/Model/Behavior/LinkSocialBehavior.php @@ -0,0 +1,141 @@ +_table->SocialAccounts->getAlias(); + $socialAccount = $this->_table->SocialAccounts->find() + ->where([ + $alias . '.reference' => $reference, + $alias . '.provider' => Hash::get($data, 'provider') + ])->first(); + + if ($socialAccount && $user->id !== $socialAccount->user_id) { + $user->setErrors([ + 'social_accounts' => [ + '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') + ] + ]); + + return $user; + } + + return $this->createOrUpdateSocialAccount($user, $data, $socialAccount); + } + + /** + * Create or update a new social account linking to the user. + * + * @param EntityInterface $user User to link. + * @param array $data Social account information. + * @param EntityInterface $socialAccount to update or create. + * + * @return EntityInterface + */ + protected function createOrUpdateSocialAccount(EntityInterface $user, $data, $socialAccount) + { + if (!$socialAccount) { + $socialAccount = $this->_table->SocialAccounts->newEntity(); + } + + $data['user_id'] = $user->id; + $socialAccount = $this->populateSocialAccount($socialAccount, $data); + + $result = $this->_table->SocialAccounts->save($socialAccount); + + $accounts = (array)$user->social_accounts; + $found = false; + foreach ($accounts as $key => $account) { + if ($account->id == $socialAccount->id) { + $accounts[$key] = $socialAccount; + $found = true; + break; + } + } + + if (!$found) { + $accounts[] = $socialAccount; + } + $user->social_accounts = $accounts; + + if ($result && !$result->getErrors()) { + return $user; + } + + return $user; + } + + /** + * Populate the social account + * + * @param EntityInterface $socialAccount to populate. + * @param array $data Social account information. + * + * @return EntityInterface + */ + protected function populateSocialAccount($socialAccount, $data) + { + $accountData = $socialAccount->toArray(); + $accountData['username'] = Hash::get($data, 'username'); + $accountData['reference'] = Hash::get($data, 'id'); + $accountData['avatar'] = Hash::get($data, 'avatar'); + $accountData['link'] = Hash::get($data, 'link'); + $accountData['avatar'] = str_replace('normal', 'square', $accountData['avatar']); + $accountData['description'] = Hash::get($data, 'bio'); + $accountData['token'] = Hash::get($data, 'credentials.token'); + $accountData['token_secret'] = Hash::get($data, 'credentials.secret'); + $accountData['user_id'] = Hash::get($data, 'user_id'); + $accountData['token_expires'] = null; + $expires = Hash::get($data, 'credentials.expires'); + if (!empty($expires)) { + $expiresTime = new Time(); + $accountData['token_expires'] = $expiresTime->setTimestamp($expires)->format('Y-m-d H:i:s'); + } + + $accountData['data'] = serialize(Hash::get($data, 'raw')); + $accountData['active'] = true; + + $socialAccount = $this->_table->SocialAccounts->patchEntity($socialAccount, $accountData); + //ensure provider is present in Entity + $socialAccount['provider'] = Hash::get($data, 'provider'); + + return $socialAccount; + } +} diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php new file mode 100644 index 000000000..2c08a0a1e --- /dev/null +++ b/src/Model/Behavior/PasswordBehavior.php @@ -0,0 +1,159 @@ +_getUser($reference); + + if (empty($user)) { + throw new UserNotFoundException(__d('CakeDC/Users', "User not found")); + } + if (Hash::get($options, 'checkActive')) { + if ($user->active) { + throw new UserAlreadyActiveException(__d('CakeDC/Users', "User account already validated")); + } + $user->active = false; + $user->activation_date = null; + } + if (Hash::get($options, 'ensureActive')) { + if (!$user['active']) { + throw new UserNotActiveException(__d('CakeDC/Users', "User not active")); + } + } + $user->updateToken($expiration); + $saveResult = $this->_table->save($user); + if (Hash::get($options, 'sendEmail')) { + switch (Hash::get($options, 'type')) { + case 'email': + $this->_sendValidationEmail($user); + break; + case 'password': + $this->_sendResetPasswordEmail($user); + break; + } + } + + return $saveResult; + } + + /** + * Send the reset password related email link + * + * @param EntityInterface $user user + * @return void + */ + protected function _sendResetPasswordEmail($user) + { + $this + ->getMailer(Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users') + ->send('resetPassword', [$user]); + } + + /** + * Wrapper for mailer + * + * @param EntityInterface $user user + * @return void + */ + protected function _sendValidationEmail($user) + { + $mailer = Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users'; + $this + ->getMailer($mailer) + ->send('validation', [$user]); + } + + /** + * Get the user by email or username + * + * @param string $reference reference could be either an email or username + * @return mixed user entity if found + */ + protected function _getUser($reference) + { + return $this->_table->findByUsernameOrEmail($reference, $reference)->first(); + } + + /** + * Change password method + * + * @param EntityInterface $user user data. + * @throws WrongPasswordException + * @return mixed + */ + public function changePassword(EntityInterface $user) + { + try { + $currentUser = $this->_table->get($user->id, [ + 'contain' => [] + ]); + } catch (RecordNotFoundException $e) { + throw new UserNotFoundException(__d('CakeDC/Users', "User not found")); + } + + if (!empty($user->current_password)) { + if (!$user->checkPassword($user->current_password, $currentUser->password)) { + throw new WrongPasswordException(__d('CakeDC/Users', 'The current password does not match')); + } + if ($user->current_password === $user->password_confirm) { + throw new WrongPasswordException(__d( + 'CakeDC/Users', + 'You cannot use the current password as the new one' + )); + } + } + $user = $this->_table->save($user); + if (!empty($user)) { + $user = $this->_removeValidationToken($user); + } + + return $user; + } +} diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php new file mode 100644 index 000000000..6700fb9f7 --- /dev/null +++ b/src/Model/Behavior/RegisterBehavior.php @@ -0,0 +1,210 @@ +validateEmail = (bool)Configure::read('Users.Email.validate'); + $this->useTos = (bool)Configure::read('Users.Tos.required'); + } + + /** + * Registers an user. + * + * @param EntityInterface $user User information + * @param array $data User information + * @param array $options ['tokenExpiration] + * @return bool|EntityInterface + */ + public function register($user, $data, $options) + { + $validateEmail = Hash::get($options, 'validate_email'); + $tokenExpiration = Hash::get($options, 'token_expiration'); + $user = $this->_table->patchEntity( + $user, + $data, + ['validate' => Hash::get($options, 'validator') ?: $this->getRegisterValidators($options)] + ); + $user['role'] = Configure::read('Users.Registration.defaultRole') ?: 'user'; + $user->validated = false; + //@todo move updateActive to afterSave? + $user = $this->_updateActive($user, $validateEmail, $tokenExpiration); + $this->_table->isValidateEmail = $validateEmail; + $userSaved = $this->_table->save($user); + if ($userSaved && $validateEmail) { + $this->_sendValidationEmail($user); + } + + return $userSaved; + } + + /** + * Validates token and return user + * + * @param string $token toke to be validated. + * @param null $callback function that will be returned. + * @throws TokenExpiredException when token has expired. + * @throws UserNotFoundException when user isn't found. + * @return EntityInterface $user + */ + public function validate($token, $callback = null) + { + $user = $this->_table->find() + ->select(['token_expires', 'id', 'active', 'token']) + ->where(['token' => $token]) + ->first(); + if (empty($user)) { + throw new UserNotFoundException(__d('CakeDC/Users', "User not found for the given token and email.")); + } + if ($user->tokenExpired()) { + throw new TokenExpiredException(__d('CakeDC/Users', "Token has already expired user with no token")); + } + if (!method_exists($this, $callback)) { + return $user; + } + + return $this->_table->{$callback}($user); + } + + /** + * Activates an user + * + * @param EntityInterface $user user object. + * @return mixed User entity or bool false if the user could not be activated + * @throws UserAlreadyActiveException + */ + public function activateUser(EntityInterface $user) + { + if ($user->active) { + throw new UserAlreadyActiveException(__d('CakeDC/Users', "User account already validated")); + } + $user->activation_date = new \DateTime(); + $user->token_expires = null; + $user->active = true; + $result = $this->_table->save($user); + + return $result; + } + + /** + * buildValidator + * + * @param Event $event event + * @param Validator $validator validator + * @param string $name name + * @return Validator + */ + public function buildValidator(Event $event, Validator $validator, $name) + { + if ($name === 'default') { + return $this->_emailValidator($validator, $this->validateEmail); + } + + return $validator; + } + + /** + * Email validator + * + * @param Validator $validator Validator instance. + * @param bool $validateEmail true when email needs to be required + * @return Validator + */ + protected function _emailValidator(Validator $validator, $validateEmail) + { + $this->validateEmail = $validateEmail; + $validator + ->add('email', 'valid', ['rule' => 'email']) + ->notEmpty('email', __d('Users', 'This field is required'), function ($context) { + return $this->validateEmail; + }); + + return $validator; + } + + /** + * Tos validator + * + * @param Validator $validator Validator instance. + * @return Validator + */ + protected function _tosValidator(Validator $validator) + { + $validator + ->requirePresence('tos', 'create') + ->notEmpty('tos'); + + return $validator; + } + + /** + * Returns the list of validators + * + * @param array $options Array of options ['validate_email' => true/false, 'use_tos' => true/false] + * @return Validator + */ + public function getRegisterValidators($options) + { + $validateEmail = Hash::get($options, 'validate_email'); + $useTos = Hash::get($options, 'use_tos'); + + $validator = $this->_table->validationDefault(new Validator()); + $validator = $this->_table->validationRegister($validator); + if ($useTos) { + $validator = $this->_tosValidator($validator); + } + + if ($validateEmail) { + $validator = $this->_emailValidator($validator, $validateEmail); + } + + return $validator; + } + + /** + * Wrapper for mailer + * + * @param EntityInterface $user user + * @return void + */ + protected function _sendValidationEmail($user) + { + $mailer = Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users'; + $this + ->getMailer($mailer) + ->send('validation', [$user]); + } +} diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php new file mode 100644 index 000000000..1ab405ab3 --- /dev/null +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -0,0 +1,152 @@ +_table->belongsTo('Users', [ + 'foreignKey' => 'user_id', + 'joinType' => 'INNER', + 'className' => Configure::read('Users.table') + ]); + } + + /** + * After save callback + * + * @param Event $event event + * @param Entity $entity entity + * @param \ArrayObject $options options + * @return mixed + */ + public function afterSave(Event $event, Entity $entity, $options) + { + if ($entity->active) { + return true; + } + $user = $this->_table->Users->find()->where(['Users.id' => $entity->user_id, 'Users.active' => true])->first(); + if (empty($user)) { + return true; + } + + return $this->sendSocialValidationEmail($entity, $user); + } + + /** + * Send social validation email to the user + * + * @param EntityInterface $socialAccount social account + * @param EntityInterface $user user + * @return void + */ + protected function sendSocialValidationEmail(EntityInterface $socialAccount, EntityInterface $user) + { + return $this + ->getMailer(Configure::read('Users.Email.mailerClass') ?: 'CakeDC/Users.Users') + ->send('socialAccountValidation', [$user, $socialAccount]); + } + + /** + * Validates the social account + * + * @param string $provider provider + * @param string $reference reference + * @param string $token token + * @throws RecordNotFoundException + * @throws AccountAlreadyActiveException + * @return User + */ + public function validateAccount($provider, $reference, $token) + { + $socialAccount = $this->_table->find() + ->select(['id', 'provider', 'reference', 'active', 'token']) + ->where(['provider' => $provider, 'reference' => $reference]) + ->first(); + + if (!empty($socialAccount) && $socialAccount->token === $token) { + if ($socialAccount->active) { + throw new AccountAlreadyActiveException(__d('CakeDC/Users', "Account already validated")); + } + } else { + throw new RecordNotFoundException(__d('CakeDC/Users', "Account not found for the given token and email.")); + } + + return $this->_activateAccount($socialAccount); + } + + /** + * Validates the social account + * + * @param string $provider provider + * @param string $reference reference + * @throws RecordNotFoundException + * @throws AccountAlreadyActiveException + * @return User + */ + public function resendValidation($provider, $reference) + { + $socialAccount = $this->_table->find() + ->where(['provider' => $provider, 'reference' => $reference]) + ->contain('Users') + ->first(); + + if (!empty($socialAccount)) { + if ($socialAccount->active) { + throw new AccountAlreadyActiveException(__d('CakeDC/Users', "Account already validated")); + } + } else { + throw new RecordNotFoundException(__d('CakeDC/Users', "Account not found for the given token and email.")); + } + + return $this->sendSocialValidationEmail($socialAccount, $socialAccount->user); + } + + /** + * Activates an account + * + * @param SocialAccount $socialAccount social account + * @return EntityInterface + */ + protected function _activateAccount($socialAccount) + { + $socialAccount->active = true; + $result = $this->_table->save($socialAccount); + + return $result; + } +} diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php new file mode 100644 index 000000000..8fbc82416 --- /dev/null +++ b/src/Model/Behavior/SocialBehavior.php @@ -0,0 +1,261 @@ +_username = $config['username']; + } + + parent::initialize($config); + } + + /** + * Performs social login + * + * @param array $data Array social login. + * @param array $options Array option data. + * @throws InvalidArgumentException + * @throws UserNotActiveException + * @throws AccountNotActiveException + * @return bool|EntityInterface|mixed + */ + public function socialLogin(array $data, array $options) + { + $reference = Hash::get($data, 'id'); + $existingAccount = $this->_table->SocialAccounts->find() + ->where([ + 'SocialAccounts.reference' => $reference, + 'SocialAccounts.provider' => Hash::get($data, 'provider') + ]) + ->contain(['Users']) + ->first(); + if (empty($existingAccount->user)) { + $user = $this->_createSocialUser($data, $options); + if (!empty($user->social_accounts[0])) { + $existingAccount = $user->social_accounts[0]; + } else { + //@todo: what if we don't have a social account after createSocialUser? + throw new InvalidArgumentException(__d('CakeDC/Users', 'Unable to login user with reference {0}', $reference)); + } + } else { + $user = $existingAccount->user; + } + if (!empty($existingAccount)) { + if (!$existingAccount->active) { + throw new AccountNotActiveException([ + $existingAccount->provider, + $existingAccount->reference + ]); + } + if (!$user->active) { + throw new UserNotActiveException([ + $existingAccount->provider, + $existingAccount->$user + ]); + } + } + + return $user; + } + + /** + * Creates social user, populate the user data based on the social login data first and save it + * + * @param array $data Array social user. + * @param array $options Array option data. + * @throws MissingEmailException + * @return bool|EntityInterface|mixed result of the save operation + */ + protected function _createSocialUser($data, $options = []) + { + $useEmail = Hash::get($options, 'use_email'); + $validateEmail = Hash::get($options, 'validate_email'); + $tokenExpiration = Hash::get($options, 'token_expiration'); + $existingUser = null; + $email = Hash::get($data, 'email'); + if ($useEmail && empty($email)) { + throw new MissingEmailException(__d('CakeDC/Users', 'Email not present')); + } else { + $existingUser = $this->_table->find() + ->where([$this->_table->aliasField('email') => $email]) + ->first(); + } + + $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); + + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_SOCIAL_LOGIN_USER_CREATE, [ + 'userEntity' => $user, + ]); + if ($event->result instanceof EntityInterface) { + $user = $event->result; + } + + $this->_table->isValidateEmail = $validateEmail; + $result = $this->_table->save($user); + + return $result; + } + + /** + * Build new user entity either by using an existing user or extracting the data from the social login + * data to create a new one + * + * @param array $data Array social login. + * @param EntityInterface $existingUser user data. + * @param string $useEmail email to use. + * @param string $validateEmail email to validate. + * @param string $tokenExpiration token_expires data. + * @return EntityInterface + * @todo refactor + */ + protected function _populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration) + { + $accountData['username'] = Hash::get($data, 'username'); + $accountData['reference'] = Hash::get($data, 'id'); + $accountData['avatar'] = Hash::get($data, 'avatar'); + $accountData['link'] = Hash::get($data, 'link'); + + $accountData['avatar'] = str_replace('normal', 'square', $accountData['avatar']); + $accountData['description'] = Hash::get($data, 'bio'); + $accountData['token'] = Hash::get($data, 'credentials.token'); + $accountData['token_secret'] = Hash::get($data, 'credentials.secret'); + $expires = Hash::get($data, 'credentials.expires'); + if (!empty($expires)) { + $expiresTime = new DateTime(); + $accountData['token_expires'] = $expiresTime->setTimestamp($expires)->format('Y-m-d H:i:s'); + } else { + $accountData['token_expires'] = null; + } + $accountData['data'] = serialize(Hash::get($data, 'raw')); + $accountData['active'] = true; + + $dataValidated = Hash::get($data, 'validated'); + + if (empty($existingUser)) { + $firstName = Hash::get($data, 'first_name'); + $lastName = Hash::get($data, 'last_name'); + if (!empty($firstName) && !empty($lastName)) { + $userData['first_name'] = $firstName; + $userData['last_name'] = $lastName; + } else { + $name = explode(' ', Hash::get($data, 'full_name')); + $userData['first_name'] = Hash::get($name, 0); + array_shift($name); + $userData['last_name'] = implode(' ', $name); + } + $userData['username'] = Hash::get($data, 'username'); + $username = Hash::get($userData, 'username'); + if (empty($username)) { + $dataEmail = Hash::get($data, 'email'); + if (!empty($dataEmail)) { + $email = explode('@', $dataEmail); + $userData['username'] = Hash::get($email, 0); + } else { + $firstName = Hash::get($userData, 'first_name'); + $lastName = Hash::get($userData, 'last_name'); + $userData['username'] = strtolower($firstName . $lastName); + $userData['username'] = preg_replace('/[^A-Za-z0-9]/i', '', Hash::get($userData, 'username')); + } + } + + $userData['username'] = $this->generateUniqueUsername(Hash::get($userData, 'username')); + if ($useEmail) { + $userData['email'] = Hash::get($data, 'email'); + if (empty($dataValidated)) { + $accountData['active'] = false; + } + } + + $userData['password'] = $this->randomString(); + $userData['avatar'] = Hash::get($data, 'avatar'); + $userData['validated'] = !empty($dataValidated); + $userData['tos_date'] = date("Y-m-d H:i:s"); + $userData['gender'] = Hash::get($data, 'gender'); + $userData['social_accounts'][] = $accountData; + + $user = $this->_table->newEntity($userData); + $user = $this->_updateActive($user, false, $tokenExpiration); + } else { + if ($useEmail && empty($dataValidated)) { + $accountData['active'] = false; + } + $user = $existingUser; + } + $socialAccount = $this->_table->SocialAccounts->newEntity($accountData); + //ensure provider is present in Entity + $socialAccount['provider'] = Hash::get($data, 'provider'); + $user['social_accounts'] = [$socialAccount]; + $user['role'] = Configure::read('Users.Registration.defaultRole') ?: 'user'; + + return $user; + } + + /** + * Checks if username exists and generate a new one + * + * @param string $username username data. + * @return string + */ + public function generateUniqueUsername($username) + { + $i = 0; + while (true) { + $existingUsername = $this->_table->find() + ->where([$this->_table->aliasField($this->_username) => $username]) + ->count(); + if ($existingUsername > 0) { + $username = $username . $i; + $i++; + continue; + } + break; + } + + return $username; + } +} diff --git a/src/Model/Entity/SocialAccount.php b/src/Model/Entity/SocialAccount.php new file mode 100644 index 000000000..9c6f421ec --- /dev/null +++ b/src/Model/Entity/SocialAccount.php @@ -0,0 +1,41 @@ + true, + 'id' => false, + ]; + + /** + * Fields that are excluded from JSON an array versions of the entity. + * + * @var array + */ + protected $_hidden = [ + 'token', + 'token_secret', + 'token_expires', + ]; +} diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php new file mode 100644 index 000000000..e4c8b8520 --- /dev/null +++ b/src/Model/Entity/User.php @@ -0,0 +1,163 @@ + true, + 'id' => false, + 'is_superuser' => false, + 'role' => false, + ]; + + /** + * Fields that are excluded from JSON an array versions of the entity. + * + * @var array + */ + protected $_hidden = [ + 'password', + 'token', + 'token_expires', + 'api_token', + ]; + + /** + * @param string $password password that will be set. + * @return bool|string + */ + protected function _setPassword($password) + { + return $this->hashPassword($password); + } + + /** + * @param string $password password that will be confirm. + * @return bool|string + */ + protected function _setConfirmPassword($password) + { + return $this->hashPassword($password); + } + + /** + * @param string $tos tos option. It will be set the tos_date + * @return bool + */ + protected function _setTos($tos) + { + if ((bool)$tos === true) { + $this->set('tos_date', Time::now()); + } + + return $tos; + } + + /** + * Hash a password using the configured password hasher, + * use DefaultPasswordHasher if no one was configured + * + * @param string $password password to be hashed + * @return mixed + */ + public function hashPassword($password) + { + $PasswordHasher = $this->getPasswordHasher(); + + return $PasswordHasher->hash($password); + } + + /** + * Return the configured Password Hasher + * + * @return mixed + */ + public function getPasswordHasher() + { + $passwordHasher = Configure::read('Users.passwordHasher'); + if (!class_exists($passwordHasher)) { + $passwordHasher = '\Cake\Auth\DefaultPasswordHasher'; + } + + return new $passwordHasher; + } + + /** + * Checks if a password is correctly hashed + * + * @param string $password password that will be check. + * @param string $hashedPassword hash used to check password. + * @return bool + */ + public function checkPassword($password, $hashedPassword) + { + $PasswordHasher = $this->getPasswordHasher(); + + return $PasswordHasher->check($password, $hashedPassword); + } + + /** + * Returns if the token has already expired + * + * @return bool + */ + public function tokenExpired() + { + if (empty($this->token_expires)) { + return true; + } + + return new Time($this->token_expires) < Time::now(); + } + + /** + * Getter for user avatar + * + * @return string|null avatar + */ + protected function _getAvatar() + { + $avatar = null; + if (!empty($this->_properties['social_accounts'][0])) { + $avatar = $this->_properties['social_accounts'][0]['avatar']; + } + + return $avatar; + } + + /** + * Generate token_expires and token in a user + * @param int $tokenExpiration seconds to expire the token from Now + * @return void + */ + public function updateToken($tokenExpiration = 0) + { + $expiration = new Time('now'); + $this->token_expires = $expiration->addSeconds($tokenExpiration); + $this->token = bin2hex(Security::randomBytes(16)); + } +} diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php new file mode 100644 index 000000000..1363dd399 --- /dev/null +++ b/src/Model/Table/SocialAccountsTable.php @@ -0,0 +1,133 @@ +setTable('social_accounts'); + $this->setDisplayField('id'); + $this->setPrimaryKey('id'); + $this->addBehavior('Timestamp'); + $this->addBehavior('CakeDC/Users.SocialAccount'); + } + + /** + * Default validation rules. + * + * @param Validator $validator Validator instance. + * @return Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->add('id', 'valid', ['rule' => 'uuid']) + ->allowEmpty('id', 'create'); + + $validator + ->requirePresence('provider', 'create') + ->notEmpty('provider'); + + $validator + ->allowEmpty('username'); + + $validator + ->requirePresence('reference', 'create') + ->notEmpty('reference'); + + $validator + ->requirePresence('link', 'create') + ->notEmpty('reference'); + + $validator + ->allowEmpty('avatar'); + + $validator + ->allowEmpty('description'); + + $validator + ->requirePresence('token', 'create') + ->notEmpty('token'); + + $validator + ->allowEmpty('token_secret'); + + $validator + ->add('token_expires', 'valid', ['rule' => 'datetime']) + ->allowEmpty('token_expires'); + + $validator + ->add('active', 'valid', ['rule' => 'boolean']) + ->requirePresence('active', 'create') + ->notEmpty('active'); + + $validator + ->requirePresence('data', 'create') + ->notEmpty('data'); + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param RulesChecker $rules The rules object to be modified. + * @return RulesChecker + */ + public function buildRules(RulesChecker $rules) + { + $rules->add($rules->existsIn(['user_id'], 'Users')); + + return $rules; + } + + /** + * Finder for active social accounts + * + * @param Query $query query + * @return \Cake\ORM\Query + */ + public function findActive(Query $query) + { + return $query->where([ + $this->aliasField('active') => true + ]); + } +} diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php new file mode 100644 index 000000000..d8e1919f7 --- /dev/null +++ b/src/Model/Table/UsersTable.php @@ -0,0 +1,185 @@ +setTable('users'); + $this->setDisplayField('username'); + $this->setPrimaryKey('id'); + $this->addBehavior('Timestamp'); + $this->addBehavior('CakeDC/Users.Register'); + $this->addBehavior('CakeDC/Users.Password'); + $this->addBehavior('CakeDC/Users.Social'); + $this->addBehavior('CakeDC/Users.LinkSocial'); + $this->addBehavior('CakeDC/Users.AuthFinder'); + $this->hasMany('SocialAccounts', [ + 'foreignKey' => 'user_id', + 'className' => 'CakeDC/Users.SocialAccounts' + ]); + } + + /** + * Adds some rules for password confirm + * @param Validator $validator Cake validator object. + * @return Validator + */ + public function validationPasswordConfirm(Validator $validator) + { + $validator + ->requirePresence('password_confirm', 'create') + ->notEmpty('password_confirm'); + + $validator + ->requirePresence('password', 'create') + ->notEmpty('password') + ->add('password', [ + 'password_confirm_check' => [ + 'rule' => ['compareWith', 'password_confirm'], + 'message' => __d('CakeDC/Users', 'Your password does not match your confirm password. Please try again'), + 'allowEmpty' => false + ]]); + + return $validator; + } + + /** + * Adds rules for current password + * + * @param Validator $validator Cake validator object. + * @return Validator + */ + public function validationCurrentPassword(Validator $validator) + { + $validator + ->notEmpty('current_password'); + + return $validator; + } + + /** + * Default validation rules. + * + * @param Validator $validator Validator instance. + * @return Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->allowEmpty('id', 'create'); + + $validator + ->requirePresence('username', 'create') + ->notEmpty('username'); + + $validator + ->requirePresence('password', 'create') + ->notEmpty('password'); + + $validator + ->allowEmpty('first_name'); + + $validator + ->allowEmpty('last_name'); + + $validator + ->allowEmpty('token'); + + $validator + ->add('token_expires', 'valid', ['rule' => 'datetime']) + ->allowEmpty('token_expires'); + + $validator + ->allowEmpty('api_token'); + + $validator + ->add('activation_date', 'valid', ['rule' => 'datetime']) + ->allowEmpty('activation_date'); + + $validator + ->add('tos_date', 'valid', ['rule' => 'datetime']) + ->allowEmpty('tos_date'); + + return $validator; + } + + /** + * Wrapper for all validation rules for register + * @param Validator $validator Cake validator object. + * + * @return Validator + */ + public function validationRegister(Validator $validator) + { + $validator = $this->validationDefault($validator); + $validator = $this->validationPasswordConfirm($validator); + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param RulesChecker $rules The rules object to be modified. + * @return RulesChecker + */ + public function buildRules(RulesChecker $rules) + { + $rules->add($rules->isUnique(['username']), '_isUnique', [ + 'errorField' => 'username', + 'message' => __d('CakeDC/Users', 'Username already exists') + ]); + + if ($this->isValidateEmail) { + $rules->add($rules->isUnique(['email']), '_isUnique', [ + 'errorField' => 'email', + 'message' => __d('CakeDC/Users', 'Email already exists') + ]); + } + + return $rules; + } +} diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php new file mode 100644 index 000000000..292dc71b3 --- /dev/null +++ b/src/Shell/UsersShell.php @@ -0,0 +1,404 @@ +Users = $this->loadModel(Configure::read('Users.table')); + } + + /** + * + * @return ConsoleOptionParser + */ + public function getOptionParser() + { + $parser = parent::getOptionParser(); + $parser->setDescription(__d('CakeDC/Users', 'Utilities for CakeDC Users Plugin')) + ->addSubcommand('activateUser', [ + 'help' => __d('CakeDC/Users', 'Activate an specific user') + ]) + ->addSubcommand('addSuperuser', [ + 'help' => __d('CakeDC/Users', 'Add a new superadmin user for testing purposes') + ]) + ->addSubcommand('addUser', [ + 'help' => __d('CakeDC/Users', 'Add a new user') + ]) + ->addSubcommand('changeRole', [ + 'help' => __d('CakeDC/Users', 'Change the role for an specific user') + ]) + ->addSubcommand('deactivateUser', [ + 'help' => __d('CakeDC/Users', 'Deactivate an specific user') + ]) + ->addSubcommand('deleteUser', [ + 'help' => __d('CakeDC/Users', 'Delete an specific user') + ]) + ->addSubcommand('passwordEmail', [ + 'help' => __d('CakeDC/Users', 'Reset the password via email') + ]) + ->addSubcommand('resetAllPasswords', [ + 'help' => __d('CakeDC/Users', 'Reset the password for all users') + ]) + ->addSubcommand('resetPassword', [ + 'help' => __d('CakeDC/Users', 'Reset the password for an specific user') + ]) + ->addOptions([ + 'username' => ['short' => 'u', 'help' => 'The username for the new user'], + 'password' => ['short' => 'p', 'help' => 'The password for the new user'], + 'email' => ['short' => 'e', 'help' => 'The email for the new user'], + 'role' => ['short' => 'r', 'help' => 'The role for the new user'] + ]); + + return $parser; + } + + /** + * Add a new user + * + * @return void + */ + public function addUser() + { + $this->_createUser(['role' => Configure::read('Users.Registration.defaultRole') ?: 'user']); + } + + /** + * Add a new superadmin user + * + * @return void + */ + public function addSuperuser() + { + $this->_createUser([ + 'username' => 'superadmin', + 'role' => 'superuser', + 'is_superuser' => true + ]); + } + + /** + * Reset password for all user + * + * Arguments: + * + * - Password to be set + * + * @return void + */ + public function resetAllPasswords() + { + $password = Hash::get($this->args, 0); + if (empty($password)) { + $this->abort(__d('CakeDC/Users', 'Please enter a password.')); + } + $hashedPassword = $this->_generatedHashedPassword($password); + $this->Users->updateAll(['password' => $hashedPassword], ['id IS NOT NULL']); + $this->out(__d('CakeDC/Users', 'Password changed for all users')); + $this->out(__d('CakeDC/Users', 'New password: {0}', $password)); + } + + /** + * Reset password for a user + * + * Arguments: + * + * - Username + * - Password to be set + * + * @return void + */ + public function resetPassword() + { + $username = Hash::get($this->args, 0); + $password = Hash::get($this->args, 1); + if (empty($username)) { + $this->abort(__d('CakeDC/Users', 'Please enter a username.')); + } + if (empty($password)) { + $this->abort(__d('CakeDC/Users', 'Please enter a password.')); + } + $data = [ + 'password' => $password + ]; + $this->_updateUser($username, $data); + $this->out(__d('CakeDC/Users', 'Password changed for user: {0}', $username)); + $this->out(__d('CakeDC/Users', 'New password: {0}', $password)); + } + + /** + * Change role for a user + * + * Arguments: + * + * - Username + * - Role to be set + * + * @return void + */ + public function changeRole() + { + $username = Hash::get($this->args, 0); + $role = Hash::get($this->args, 1); + if (empty($username)) { + $this->abort(__d('CakeDC/Users', 'Please enter a username.')); + } + if (empty($role)) { + $this->abort(__d('CakeDC/Users', 'Please enter a role.')); + } + $data = [ + 'role' => $role + ]; + $savedUser = $this->_updateUser($username, $data); + $this->out(__d('CakeDC/Users', 'Role changed for user: {0}', $username)); + $this->out(__d('CakeDC/Users', 'New role: {0}', $savedUser->role)); + } + + /** + * Activate an specific user + * + * Arguments: + * + * - Username + * + * @return void + */ + public function activateUser() + { + $user = $this->_changeUserActive(true); + $this->out(__d('CakeDC/Users', 'User was activated: {0}', $user->username)); + } + + /** + * De-activate an specific user + * + * Arguments: + * + * - Username + * + * @return void + */ + public function deactivateUser() + { + $user = $this->_changeUserActive(false); + $this->out(__d('CakeDC/Users', 'User was de-activated: {0}', $user->username)); + } + + /** + * Reset password via email for user + * + * @return void + */ + public function passwordEmail() + { + $reference = Hash::get($this->args, 0); + if (empty($reference)) { + $this->abort(__d('CakeDC/Users', 'Please enter a username or email.')); + } + $resetUser = $this->Users->resetToken($reference, [ + 'expiration' => Configure::read('Users.Token.expiration'), + 'checkActive' => false, + 'sendEmail' => true, + ]); + if ($resetUser) { + $msg = __d('CakeDC/Users', 'Please ask the user to check the email to continue with password reset process'); + $this->out($msg); + } else { + $msg = __d('CakeDC/Users', 'The password token could not be generated. Please try again'); + $this->abort($msg); + } + } + + /** + * Change user active field + * + * @param bool $active active value + * @return bool + */ + protected function _changeUserActive($active) + { + $username = Hash::get($this->args, 0); + if (empty($username)) { + $this->abort(__d('CakeDC/Users', 'Please enter a username.')); + } + $data = [ + 'active' => $active + ]; + + return $this->_updateUser($username, $data); + } + + /** + * Create a new user or superuser + * + * @param array $template template with deafault user values + * @return void + */ + protected function _createUser($template) + { + if (!empty($this->params['username'])) { + $username = $this->params['username']; + } else { + $username = !empty($template['username']) ? + $template['username'] : $this->_generateRandomUsername(); + } + + $password = (empty($this->params['password']) ? + $this->_generateRandomPassword() : $this->params['password']); + $email = (empty($this->params['email']) ? + $username . '@example.com' : $this->params['email']); + $role = (empty($this->params['role']) ? + $template['role'] : $this->params['role']); + + $user = [ + 'username' => $this->Users->generateUniqueUsername($username), + 'email' => $email, + 'password' => $password, + 'active' => 1, + ]; + + $userEntity = $this->Users->newEntity($user); + $userEntity->is_superuser = empty($template['is_superuser']) ? + false : $template['is_superuser']; + $userEntity->role = $role; + $savedUser = $this->Users->save($userEntity); + + if (!empty($savedUser)) { + if ($savedUser->is_superuser) { + $this->out(__d('CakeDC/Users', 'Superuser added:')); + } else { + $this->out(__d('CakeDC/Users', 'User added:')); + } + $this->out(__d('CakeDC/Users', 'Id: {0}', $savedUser->id)); + $this->out(__d('CakeDC/Users', 'Username: {0}', $savedUser->username)); + $this->out(__d('CakeDC/Users', 'Email: {0}', $savedUser->email)); + $this->out(__d('CakeDC/Users', 'Role: {0}', $savedUser->role)); + $this->out(__d('CakeDC/Users', 'Password: {0}', $password)); + } else { + $this->out(__d('CakeDC/Users', 'User could not be added:')); + + collection($userEntity->getErrors())->each(function ($error, $field) { + $this->out(__d('CakeDC/Users', 'Field: {0} Error: {1}', $field, implode(',', $error))); + }); + } + } + + /** + * Update user by username + * + * @param string $username username + * @param array $data data + * @return bool + */ + protected function _updateUser($username, $data) + { + $user = $this->Users->find()->where(['username' => $username])->first(); + if (empty($user)) { + $this->abort(__d('CakeDC/Users', 'The user was not found.')); + } + $user = $this->Users->patchEntity($user, $data); + collection($data)->filter(function ($value, $field) use ($user) { + return !$user->isAccessible($field); + })->each(function ($value, $field) use (&$user) { + $user->{$field} = $value; + }); + $savedUser = $this->Users->save($user); + + return $savedUser; + } + + /** + * Delete an specific user and associated social accounts + * + * @return void + */ + public function deleteUser() + { + $username = Hash::get($this->args, 0); + if (empty($username)) { + $this->abort(__d('CakeDC/Users', 'Please enter a username.')); + } + $user = $this->Users->find()->where(['username' => $username])->first(); + if (isset($this->Users->SocialAccounts)) { + $this->Users->SocialAccounts->deleteAll(['user_id' => $user->id]); + } + $deleteUser = $this->Users->delete($user); + if (!$deleteUser) { + $this->abort(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); + } + $this->out(__d('CakeDC/Users', 'The user {0} was deleted successfully', $username)); + } + + /** + * Generates a random password. + * + * @return string + */ + protected function _generateRandomPassword() + { + return str_replace('-', '', Text::uuid()); + } + + /** + * Generates a random username based on a list of preexisting ones. + * + * @return string + */ + protected function _generateRandomUsername() + { + return $this->_usernameSeed[array_rand($this->_usernameSeed)]; + } + + /** + * Hash a password + * + * @param string $password password + * @return string + */ + protected function _generatedHashedPassword($password) + { + return (new User)->hashPassword($password); + } + //add filters LIKE in username and email to some tasks + // --force to ignore "you are about to do X to Y users" +} diff --git a/src/Template/Email/html/reset_password.ctp b/src/Template/Email/html/reset_password.ctp new file mode 100644 index 000000000..f6055a1d4 --- /dev/null +++ b/src/Template/Email/html/reset_password.ctp @@ -0,0 +1,35 @@ + true, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'resetPassword', + isset($token) ? $token : '' +]; +?> +

+ , +

+

+ Html->link(__d('CakeDC/Users', 'Reset your password here'), $activationUrl) ?> +

+

+Url->build($activationUrl) +) ?> +

+

+ , +

diff --git a/src/Template/Email/html/social_account_validation.ctp b/src/Template/Email/html/social_account_validation.ctp new file mode 100644 index 000000000..acef3fbc5 --- /dev/null +++ b/src/Template/Email/html/social_account_validation.ctp @@ -0,0 +1,40 @@ + + +

+ , +

+

+ true, + 'plugin' => 'CakeDC/Users', + 'controller' => 'SocialAccounts', + 'action' => 'validateAccount', + $socialAccount['provider'], + $socialAccount['reference'], + $socialAccount['token'], + ]; + echo $this->Html->link($text, $activationUrl); + ?> +

+

+Url->build($activationUrl) +) ?> +

+

+ , +

diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp new file mode 100644 index 000000000..8a1840468 --- /dev/null +++ b/src/Template/Email/html/validation.ctp @@ -0,0 +1,35 @@ + true, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'validateEmail', + isset($token) ? $token : '' +]; +?> +

+ , +

+

+ Html->link(__d('CakeDC/Users', 'Activate your account here'), $activationUrl) ?> +

+

+Url->build($activationUrl) +) ?> +

+

+ , +

diff --git a/src/Template/Email/text/reset_password.ctp b/src/Template/Email/text/reset_password.ctp new file mode 100644 index 000000000..96f001565 --- /dev/null +++ b/src/Template/Email/text/reset_password.ctp @@ -0,0 +1,29 @@ + true, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'resetPassword', + isset($token) ? $token : '' +]; +?> +, + +Url->build($activationUrl) +) ?> + +, + diff --git a/src/Template/Email/text/social_account_validation.ctp b/src/Template/Email/text/social_account_validation.ctp new file mode 100644 index 000000000..87e2d6813 --- /dev/null +++ b/src/Template/Email/text/social_account_validation.ctp @@ -0,0 +1,31 @@ + true, + 'plugin' => 'CakeDC/Users', + 'controller' => 'SocialAccounts', + 'action' => 'validateAccount', + $socialAccount['provider'], + $socialAccount['reference'], + $socialAccount['token'], +]; +?> +, + +Url->build($activationUrl) +) ?> + +, + diff --git a/src/Template/Email/text/validation.ctp b/src/Template/Email/text/validation.ctp new file mode 100644 index 000000000..ecf9d96a8 --- /dev/null +++ b/src/Template/Email/text/validation.ctp @@ -0,0 +1,29 @@ + true, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'validateEmail', + isset($token) ? $token : '' +]; +?> +, + +Url->build($activationUrl) +) ?> + +, + diff --git a/src/Template/Layout/Email/html/default.ctp b/src/Template/Layout/Email/html/default.ctp new file mode 100644 index 000000000..b0c828681 --- /dev/null +++ b/src/Template/Layout/Email/html/default.ctp @@ -0,0 +1,20 @@ + + + + + <?= $this->fetch('title') ?> + + + fetch('content') ?> + + diff --git a/src/Template/Layout/Email/text/default.ctp b/src/Template/Layout/Email/text/default.ctp new file mode 100644 index 000000000..686aa84ab --- /dev/null +++ b/src/Template/Layout/Email/text/default.ctp @@ -0,0 +1,13 @@ + +fetch('content'); diff --git a/src/Template/Users/add.ctp b/src/Template/Users/add.ctp new file mode 100644 index 000000000..751b2f3c6 --- /dev/null +++ b/src/Template/Users/add.ctp @@ -0,0 +1,36 @@ + +
+

+
    +
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • +
+
+
+ Form->create(${$tableAlias}); ?> +
+ + Form->control('username', ['label' => __d('CakeDC/Users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('CakeDC/Users', 'Email')]); + echo $this->Form->control('password', ['label' => __d('CakeDC/Users', 'Password')]); + echo $this->Form->control('first_name', ['label' => __d('CakeDC/Users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); + echo $this->Form->control('active', [ + 'type' => 'checkbox', + 'label' => __d('CakeDC/Users', 'Active') + ]); + ?> +
+ Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Users/change_password.ctp b/src/Template/Users/change_password.ctp new file mode 100644 index 000000000..339f2fc65 --- /dev/null +++ b/src/Template/Users/change_password.ctp @@ -0,0 +1,27 @@ +
+ Flash->render('auth') ?> + Form->create($user) ?> +
+ + + Form->control('current_password', [ + 'type' => 'password', + 'required' => true, + 'label' => __d('CakeDC/Users', 'Current password')]); + ?> + + Form->control('password', [ + 'type' => 'password', + 'required' => true, + 'label' => __d('CakeDC/Users', 'New password')]); + ?> + Form->control('password_confirm', [ + 'type' => 'password', + 'required' => true, + 'label' => __d('CakeDC/Users', 'Confirm password')]); + ?> + +
+ Form->button(__d('CakeDC/Users', 'Submit')); ?> + Form->end() ?> +
\ No newline at end of file diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp new file mode 100644 index 000000000..91794b822 --- /dev/null +++ b/src/Template/Users/edit.ctp @@ -0,0 +1,77 @@ + +
+

+
    +
  • + Form->postLink( + __d('CakeDC/Users', 'Delete'), + ['action' => 'delete', $Users->id], + ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $Users->id)] + ); + ?> +
  • +
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • +
+
+
+ Form->create($Users); ?> +
+ + Form->control('username', ['label' => __d('CakeDC/Users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('CakeDC/Users', 'Email')]); + echo $this->Form->control('first_name', ['label' => __d('CakeDC/Users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); + echo $this->Form->control('token', ['label' => __d('CakeDC/Users', 'Token')]); + echo $this->Form->control('token_expires', [ + 'label' => __d('CakeDC/Users', 'Token expires') + ]); + echo $this->Form->control('api_token', [ + 'label' => __d('CakeDC/Users', 'API token') + ]); + echo $this->Form->control('activation_date', [ + 'label' => __d('CakeDC/Users', 'Activation date') + ]); + echo $this->Form->control('tos_date', [ + 'label' => __d('CakeDC/Users', 'TOS date') + ]); + echo $this->Form->control('active', [ + 'label' => __d('CakeDC/Users', 'Active') + ]); + ?> +
+ Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->end() ?> + +
+ Reset Google Authenticator + Form->postLink( + __d('CakeDC/Users', 'Reset Google Authenticator Token'), [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'resetGoogleAuthenticator', $Users->id + ], [ + 'class' => 'btn btn-danger', + 'confirm' => __d( + 'CakeDC/Users', + 'Are you sure you want to reset token for user "{0}"?', $Users->username + ) + ]); + ?> +
+ +
diff --git a/src/Template/Users/index.ctp b/src/Template/Users/index.ctp new file mode 100644 index 000000000..6c9e49871 --- /dev/null +++ b/src/Template/Users/index.ctp @@ -0,0 +1,55 @@ + +
+

+
    +
  • Html->link(__d('CakeDC/Users', 'New {0}', $tableAlias), ['action' => 'add']) ?>
  • +
+
+
+ + + + + + + + + + + + + + + + + + + + + + +
Paginator->sort('username', __d('CakeDC/Users', 'Username')) ?>Paginator->sort('email', __d('CakeDC/Users', 'Email')) ?>Paginator->sort('first_name', __d('CakeDC/Users', 'First name')) ?>Paginator->sort('last_name', __d('CakeDC/Users', 'Last name')) ?>
username) ?>email) ?>first_name) ?>last_name) ?> + Html->link(__d('CakeDC/Users', 'View'), ['action' => 'view', $user->id]) ?> + Html->link(__d('CakeDC/Users', 'Change password'), ['action' => 'changePassword', $user->id]) ?> + Html->link(__d('CakeDC/Users', 'Edit'), ['action' => 'edit', $user->id]) ?> + Form->postLink(__d('CakeDC/Users', 'Delete'), ['action' => 'delete', $user->id], ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $user->id)]) ?> +
+
+
    + Paginator->prev('< ' . __d('CakeDC/Users', 'previous')) ?> + Paginator->numbers() ?> + Paginator->next(__d('CakeDC/Users', 'next') . ' >') ?> +
+

Paginator->counter() ?>

+
+
diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp new file mode 100644 index 000000000..5e08f7cd6 --- /dev/null +++ b/src/Template/Users/login.ctp @@ -0,0 +1,50 @@ + +
+ Flash->render('auth') ?> + Form->create() ?> +
+ + Form->control('username', ['label' => __d('CakeDC/Users', 'Username'), 'required' => true]) ?> + Form->control('password', ['label' => __d('CakeDC/Users', 'Password'), 'required' => true]) ?> + User->addReCaptcha(); + } + if (Configure::read('Users.RememberMe.active')) { + echo $this->Form->control(Configure::read('Users.Key.Data.rememberMe'), [ + 'type' => 'checkbox', + 'label' => __d('CakeDC/Users', 'Remember me'), + 'checked' => Configure::read('Users.RememberMe.checked') + ]); + } + ?> + Html->link(__d('CakeDC/Users', 'Register'), ['action' => 'register']); + } + if (Configure::read('Users.Email.required')) { + if ($registrationActive) { + echo ' | '; + } + echo $this->Html->link(__d('CakeDC/Users', 'Reset Password'), ['action' => 'requestResetPassword']); + } + ?> +
+ User->socialLoginList()); ?> + Form->button(__d('CakeDC/Users', 'Login')); ?> + Form->end() ?> +
diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp new file mode 100644 index 000000000..8b59d9ee2 --- /dev/null +++ b/src/Template/Users/profile.ctp @@ -0,0 +1,78 @@ + +
+

Html->image( + empty($user->avatar) ? $avatarPlaceholder : $user->avatar, + ['width' => '180', 'height' => '180'] + ); ?>

+

+ Html->tag( + 'span', + __d('CakeDC/Users', '{0} {1}', $user->first_name, $user->last_name), + ['class' => 'full_name'] + ) + ?> +

+ + Html->link(__d('CakeDC/Users', 'Change Password'), ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'changePassword']); ?> +
+
+
+

username) ?>

+
+

email) ?>

+ User->socialConnectLinkList($user->social_accounts) ?> + social_accounts)): + ?> +
+ + + + + + + + + + social_accounts as $socialAccount): + $escapedUsername = h($socialAccount->username); + $linkText = empty($escapedUsername) ? __d('CakeDC/Users', 'Link to {0}', h($socialAccount->provider)) : h($socialAccount->username) + ?> + + + + + + + +
Html->image( + $socialAccount->avatar, + ['width' => '90', 'height' => '90'] + ) ?> + provider) ?>Html->link( + $linkText, + $socialAccount->link, + ['target' => '_blank'] + ) ?>
+ +
+
+
diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp new file mode 100644 index 000000000..5a62448a0 --- /dev/null +++ b/src/Template/Users/register.ctp @@ -0,0 +1,38 @@ + +
+ Form->create($user); ?> +
+ + Form->control('username', ['label' => __d('CakeDC/Users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('CakeDC/Users', 'Email')]); + echo $this->Form->control('password', ['label' => __d('CakeDC/Users', 'Password')]); + echo $this->Form->control('password_confirm', [ + 'type' => 'password', + 'label' => __d('CakeDC/Users', 'Confirm password') + ]); + echo $this->Form->control('first_name', ['label' => __d('CakeDC/Users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('CakeDC/Users', 'Last name')]); + if (Configure::read('Users.Tos.required')) { + echo $this->Form->control('tos', ['type' => 'checkbox', 'label' => __d('CakeDC/Users', 'Accept TOS conditions?'), 'required' => true]); + } + if (Configure::read('Users.reCaptcha.registration')) { + echo $this->User->addReCaptcha(); + } + ?> +
+ Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Users/request_reset_password.ctp b/src/Template/Users/request_reset_password.ctp new file mode 100644 index 000000000..e406ff573 --- /dev/null +++ b/src/Template/Users/request_reset_password.ctp @@ -0,0 +1,10 @@ +
+ Flash->render('auth') ?> + Form->create('User') ?> +
+ + Form->control('reference') ?> +
+ Form->button(__d('CakeDC/Users', 'Submit')); ?> + Form->end() ?> +
diff --git a/src/Template/Users/resend_token_validation.ctp b/src/Template/Users/resend_token_validation.ctp new file mode 100644 index 000000000..2d2680fbe --- /dev/null +++ b/src/Template/Users/resend_token_validation.ctp @@ -0,0 +1,22 @@ + +
+ Form->create($user); ?> +
+ + Form->control('reference', ['label' => __d('CakeDC/Users', 'Email or username')]); + ?> +
+ Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Users/social_email.ctp b/src/Template/Users/social_email.ctp new file mode 100644 index 000000000..b0a272b6d --- /dev/null +++ b/src/Template/Users/social_email.ctp @@ -0,0 +1,21 @@ + +
+ Flash->render() ?> + Form->create('User') ?> +
+ + Form->control('email') ?> +
+ Form->button(__d('CakeDC/Users', 'Submit')); ?> + Form->end() ?> +
diff --git a/src/Template/Users/verify.ctp b/src/Template/Users/verify.ctp new file mode 100644 index 000000000..f1f7d2524 --- /dev/null +++ b/src/Template/Users/verify.ctp @@ -0,0 +1,20 @@ +
+
+
+
+ Form->create() ?> + + Flash->render('auth') ?> + Flash->render() ?> +
+ +

+ + Form->control('code', ['required' => true, 'label' => __d('CakeDC/Users', 'Verification Code')]) ?> +
+ Form->button(__d('CakeDC/Users', ' Verify'), ['class' => 'btn btn-primary']); ?> + Form->end() ?> +
+
+
+
diff --git a/src/Template/Users/view.ctp b/src/Template/Users/view.ctp new file mode 100644 index 000000000..d2e21bf7a --- /dev/null +++ b/src/Template/Users/view.ctp @@ -0,0 +1,90 @@ + +
+

+
    +
  • Html->link(__d('CakeDC/Users', 'Edit User'), ['action' => 'edit', $Users->id]) ?>
  • +
  • Form->postLink( + __d('CakeDC/Users', 'Delete User'), + ['action' => 'delete', $Users->id], + ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $Users->id)] + ) ?>
  • +
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • +
  • Html->link(__d('CakeDC/Users', 'New User'), ['action' => 'add']) ?>
  • +
+
+
+

id) ?>

+
+
+
+

id) ?>

+
+

username) ?>

+
+

email) ?>

+
+

first_name) ?>

+
+

last_name) ?>

+
+

role) ?>

+
+

token) ?>

+
+

api_token) ?>

+
+
+
+

Number->format($Users->active) ?>

+
+
+
+

token_expires) ?>

+
+

activation_date) ?>

+
+

tos_date) ?>

+
+

created) ?>

+
+

modified) ?>

+
+
+
+ diff --git a/src/Traits/RandomStringTrait.php b/src/Traits/RandomStringTrait.php new file mode 100644 index 000000000..668a0c828 --- /dev/null +++ b/src/Traits/RandomStringTrait.php @@ -0,0 +1,30 @@ +isAuthorized($url)) { + return Hash::get($options, 'before') . + parent::link($title, $url, $linkOptions) . + Hash::get($options, 'after'); + } + + return false; + } + + /** + * Returns true if the target url is authorized for the logged in user + * + * @param string|array|null $url url that the user is making request. + * @return bool + */ + public function isAuthorized($url = null) + { + $event = new Event(UsersAuthComponent::EVENT_IS_AUTHORIZED, $this, ['url' => $url]); + $result = EventManager::instance()->dispatch($event); + + return $result->result; + } +} diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php new file mode 100644 index 000000000..ba23e5c0c --- /dev/null +++ b/src/View/Helper/UserHelper.php @@ -0,0 +1,254 @@ +Html->tag('i', '', [ + 'class' => 'fa fa-' . strtolower($name), + ]); + + if (isset($options['title'])) { + $providerTitle = $options['title']; + } else { + $providerTitle = Hash::get($options, 'label') . ' ' . Inflector::camelize($name); + } + + $providerClass = 'btn btn-social btn-' . strtolower($name) . ((Hash::get($options, 'class')) ? ' ' . Hash::get($options, 'class') : ''); + + return $this->Html->link($icon . $providerTitle, "/auth/$name", [ + 'escape' => false, 'class' => $providerClass, + ]); + } + + /** + * All available Social Login Icons + * + * @param array $providerOptions Provider link options. + * @return array Links to Social Login Urls + */ + public function socialLoginList(array $providerOptions = []) + { + if (!Configure::read('Users.Social.login')) { + return []; + } + $outProviders = []; + $providers = Configure::read('OAuth.providers'); + foreach ($providers as $provider => $options) { + if (!empty($options['options']['redirectUri']) && + !empty($options['options']['clientId']) && + !empty($options['options']['clientSecret']) + ) { + if (isset($providerOptions[$provider])) { + $options['options'] = Hash::merge($options['options'], $providerOptions[$provider]); + } + + $outProviders[] = $this->socialLogin($provider, $options['options']); + } + } + + return $outProviders; + } + + /** + * Logout link + * + * @param null $message logout message info. + * @param array $options Array with option data. + * @return string + */ + public function logout($message = null, $options = []) + { + return $this->AuthLink->link(empty($message) ? __d('CakeDC/Users', 'Logout') : $message, [ + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout', + ], $options); + } + + /** + * Welcome display + * @return mixed + */ + public function welcome() + { + $userId = $this->request->getSession()->read('Auth.User.id'); + if (empty($userId)) { + return; + } + + $profileUrl = Configure::read('Users.Profile.route'); + $label = __d('CakeDC/Users', 'Welcome, {0}', $this->AuthLink->link($this->request->getSession()->read('Auth.User.first_name') ?: $this->request->getSession()->read('Auth.User.username'), $profileUrl)); + + return $this->Html->tag('span', $label, ['class' => 'welcome']); + } + + /** + * Add reCaptcha script + * @return void + */ + public function addReCaptchaScript() + { + $this->Html->script('https://www.google.com/recaptcha/api.js', [ + 'block' => 'script', + ]); + } + + /** + * Add reCaptcha to the form + * @return mixed + */ + public function addReCaptcha() + { + if (!Configure::read('Users.reCaptcha.key')) { + return $this->Html->tag('p', __d('CakeDC/Users', 'reCaptcha is not configured! Please configure Users.reCaptcha.key')); + } + $this->addReCaptchaScript(); + $this->Form->unlockField('g-recaptcha-response'); + + return $this->Html->tag('div', '', [ + 'class' => 'g-recaptcha', + 'data-sitekey' => Configure::read('Users.reCaptcha.key'), + 'data-theme' => Configure::read('Users.reCaptcha.theme') ?: 'light', + 'data-size' => Configure::read('Users.reCaptcha.size') ?: 'normal', + 'data-tabindex' => Configure::read('Users.reCaptcha.tabindex') ?: '3', + ]); + } + + /** + * Generate a link if the target url is authorized for the logged in user + * + * @deprecated Since 3.2.1. Use AuthLinkHelper::link() instead + * + * @param string $title link's title. + * @param string|array|null $url url that the user is making request. + * @param array $options Array with option data. + * @return string + */ + public function link($title, $url = null, array $options = []) + { + trigger_error( + 'UserHelper::link() deprecated since 3.2.1. Use AuthLinkHelper::link() instead', + E_USER_DEPRECATED + ); + + return $this->AuthLink->link($title, $url, $options); + } + + /** + * Returns true if the target url is authorized for the logged in user + * + * @deprecated Since 3.2.1. Use AuthLinkHelper::link() instead + * + * @param string|array|null $url url that the user is making request. + * @return bool + */ + public function isAuthorized($url = null) + { + trigger_error( + 'UserHelper::isAuthorized() deprecated since 3.2.1. Use AuthLinkHelper::isAuthorized() instead', + E_USER_DEPRECATED + ); + + return $this->AuthLink->isAuthorized($url); + } + /** + * Create links for all social providers enabled social link (connect) + * + * @param string $name Provider name in lowercase + * @param array $provider Provider configuration + * @param bool $isConnected User is connected with this provider + * + * @return string + */ + public function socialConnectLink($name, $provider, $isConnected = false) + { + $linkClass = 'btn btn-social btn-' . strtolower($name) . ((Hash::get($provider['options'], 'class')) ? ' ' . Hash::get($provider['options'], 'class') : ''); + if ($isConnected) { + $title = __d('CakeDC/Users', 'Connected with {0}', Inflector::camelize($name)); + + return "
$title"; + } + + $title = __d('CakeDC/Users', 'Connect with {0}', Inflector::camelize($name)); + + return $this->Html->link( + " $title", + "/link-social/$name", + [ + 'escape' => false, + 'class' => $linkClass, + ] + ); + } + + /** + * Create links for all social providers enabled social link (connect) + * + * @param array $socialAccounts All social accounts connected by a user. + * + * @return string + */ + public function socialConnectLinkList($socialAccounts = []) + { + if (!Configure::read('Users.Social.login')) { + return ""; + } + $html = ""; + $connectedProviders = array_map( + function ($item) { + return strtolower($item->provider); + }, + (array)$socialAccounts + ); + + $providers = Configure::read('OAuth.providers'); + foreach ($providers as $name => $provider) { + if (!empty($provider['options']['callbackLinkSocialUri']) && + !empty($provider['options']['linkSocialUri']) && + !empty($provider['options']['clientId']) && + !empty($provider['options']['clientSecret']) + ) { + $html .= $this->socialConnectLink($name, $provider, in_array($name, $connectedProviders)); + } + } + + return $html; + } +} diff --git a/tests/App/Controller/AppController.php b/tests/App/Controller/AppController.php new file mode 100644 index 000000000..4afebdf12 --- /dev/null +++ b/tests/App/Controller/AppController.php @@ -0,0 +1,33 @@ +loadComponent('Flash'); + // $this->loadComponent('CakeDC/Users.UsersAuth'); + $this->loadComponent('RequestHandler'); + } +} diff --git a/tests/App/Mailer/OverrideMailer.php b/tests/App/Mailer/OverrideMailer.php new file mode 100644 index 000000000..3affd4dc0 --- /dev/null +++ b/tests/App/Mailer/OverrideMailer.php @@ -0,0 +1,34 @@ +setSubject('This is the new subject'); + $this->setTemplate('custom-template-in-app-namespace'); + } +} diff --git a/tests/App/Template/Email/text/custom_template_in_app_namespace.ctp b/tests/App/Template/Email/text/custom_template_in_app_namespace.ctp new file mode 100644 index 000000000..1619a4eb2 --- /dev/null +++ b/tests/App/Template/Email/text/custom_template_in_app_namespace.ctp @@ -0,0 +1 @@ +some custom template here \ No newline at end of file diff --git a/tests/App/Template/Layout/Email/html/default.ctp b/tests/App/Template/Layout/Email/html/default.ctp new file mode 100644 index 000000000..21c7e0044 --- /dev/null +++ b/tests/App/Template/Layout/Email/html/default.ctp @@ -0,0 +1,2 @@ +fetch('content'); diff --git a/tests/App/Template/Layout/Email/text/default.ctp b/tests/App/Template/Layout/Email/text/default.ctp new file mode 100644 index 000000000..21c7e0044 --- /dev/null +++ b/tests/App/Template/Layout/Email/text/default.ctp @@ -0,0 +1,2 @@ +fetch('content'); diff --git a/tests/Fixture/PostsFixture.php b/tests/Fixture/PostsFixture.php new file mode 100644 index 000000000..257e98be2 --- /dev/null +++ b/tests/Fixture/PostsFixture.php @@ -0,0 +1,60 @@ + ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'title' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'user_id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + ], + '_options' => [ + 'engine' => 'InnoDB', + 'collation' => 'utf8_general_ci' + ], + ]; + // @codingStandardsIgnoreEnd + + /** + * Records + * + * @var array + */ + public $records = [ + [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'title' => 'post-1', + 'user_id' => '00000000-0000-0000-0000-000000000001', + ], + [ + 'id' => '00000000-0000-0000-0000-000000000002', + 'title' => 'post-2', + 'user_id' => '00000000-0000-0000-0000-000000000002', + ], + ]; +} diff --git a/tests/Fixture/PostsUsersFixture.php b/tests/Fixture/PostsUsersFixture.php new file mode 100644 index 000000000..8b5948f5d --- /dev/null +++ b/tests/Fixture/PostsUsersFixture.php @@ -0,0 +1,60 @@ + ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'user_id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'post_id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + ], + '_options' => [ + 'engine' => 'InnoDB', + 'collation' => 'utf8_general_ci' + ], + ]; + // @codingStandardsIgnoreEnd + + /** + * Records + * + * @var array + */ + public $records = [ + [ + 'id' => '00000000-0000-0000-0000-000000000011', + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'post_id' => '00000000-0000-0000-0000-000000000001', + ], + [ + 'id' => '00000000-0000-0000-0000-000000000012', + 'user_id' => '00000000-0000-0000-0000-000000000002', + 'post_id' => '00000000-0000-0000-0000-000000000002', + ], + ]; +} diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php new file mode 100644 index 000000000..48a966eda --- /dev/null +++ b/tests/Fixture/SocialAccountsFixture.php @@ -0,0 +1,141 @@ + ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'user_id' => ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'provider' => ['type' => 'string', 'length' => 255, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'autoIncrement' => null], + 'username' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'reference' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'avatar' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'description' => ['type' => 'text', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], + 'token' => ['type' => 'string', 'length' => 500, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'token_secret' => ['type' => 'string', 'length' => 500, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'token_expires' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], + 'active' => ['type' => 'boolean', 'length' => null, 'null' => false, 'default' => true, 'comment' => '', 'precision' => null], + 'data' => ['type' => 'text', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'created' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'modified' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + ], + '_options' => [ + 'engine' => 'InnoDB', + 'collation' => 'utf8_general_ci' + ], + ]; + // @codingStandardsIgnoreEnd + + /** + * Records + * + * @var array + */ + public $records = [ + [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'provider' => 'Facebook', + 'username' => 'user-1-fb', + 'reference' => 'reference-1-1234', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', + 'token' => 'token-1234', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => false, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000002', + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'provider' => 'Twitter', + 'username' => 'user-1-tw', + 'reference' => 'reference-1-1234', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => '', + 'token' => 'token-1234', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => true, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000003', + 'user_id' => '00000000-0000-0000-0000-000000000002', + 'provider' => 'Facebook', + 'username' => 'user-2-fb', + 'reference' => 'reference-2-1', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => '', + 'token' => 'token-reference-2-1', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => true, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000004', + 'user_id' => '00000000-0000-0000-0000-000000000003', + 'provider' => 'Twitter', + 'username' => 'user-2-tw', + 'reference' => 'reference-2-2', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => '', + 'token' => 'token-reference-2-2', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => false, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000005', + 'user_id' => '00000000-0000-0000-0000-000000000004', + 'provider' => 'Twitter', + 'username' => 'user-2-tw', + 'reference' => 'reference-2-2', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => '', + 'token' => 'token-reference-2-2', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => false, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ], + ]; +} diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php new file mode 100644 index 000000000..d0256aed8 --- /dev/null +++ b/tests/Fixture/UsersFixture.php @@ -0,0 +1,267 @@ + ['type' => 'uuid', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'username' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'email' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'password' => ['type' => 'string', 'length' => 255, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'first_name' => ['type' => 'string', 'length' => 50, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'last_name' => ['type' => 'string', 'length' => 50, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'token' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'token_expires' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], + 'api_token' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'activation_date' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], + 'secret' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null, 'fixed' => null], + 'secret_verified' => ['type' => 'boolean', 'length' => null, 'null' => true, 'default' => false, 'comment' => '', 'precision' => null], + 'tos_date' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], + 'active' => ['type' => 'boolean', 'length' => null, 'null' => false, 'default' => true, 'comment' => '', 'precision' => null], + 'is_superuser' => ['type' => 'boolean', 'length' => null, 'unsigned' => false, 'null' => false, 'default' => false, 'comment' => '', 'precision' => null, 'autoIncrement' => null], + 'role' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => 'user', 'comment' => '', 'precision' => null, 'fixed' => null], + 'created' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'modified' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + ], + '_options' => [ + 'engine' => 'InnoDB', + 'collation' => 'utf8_general_ci' + ], + ]; + // @codingStandardsIgnoreEnd + + /** + * Records + * + * @var array + */ + public $records = [ + [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'username' => 'user-1', + 'email' => 'user-1@test.com', + 'password' => '12345', + 'first_name' => 'first1', + 'last_name' => 'last1', + 'token' => 'ae93ddbe32664ce7927cf0c5c5a5e59d', + 'token_expires' => '2035-06-24 17:33:54', + 'api_token' => 'yyy', + 'activation_date' => '2015-06-24 17:33:54', + 'secret' => 'yyy', + 'secret_verified' => false, + 'tos_date' => '2015-06-24 17:33:54', + 'active' => false, + 'is_superuser' => true, + 'role' => 'admin', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000002', + 'username' => 'user-2', + 'email' => 'user-2@test.com', + 'password' => '12345', + 'first_name' => 'user', + 'last_name' => 'second', + 'token' => '6614f65816754310a5f0553436dd89e9', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'xxx', + 'activation_date' => '2015-06-24 17:33:54', + 'secret' => 'xxx', + 'secret_verified' => false, + 'tos_date' => '2015-06-24 17:33:54', + 'active' => true, + 'is_superuser' => true, + 'role' => 'admin', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000003', + 'username' => 'user-3', + 'email' => 'user-3@test.com', + 'password' => '12345', + 'first_name' => 'user', + 'last_name' => 'third', + 'token' => 'token-3', + 'token_expires' => '2030-06-20 17:33:54', + 'api_token' => 'xxx', + 'activation_date' => '2015-06-24 17:33:54', + 'secret' => 'xxx', + 'secret_verified' => true, + 'is_superuser' => true, + 'tos_date' => '2015-06-24 17:33:54', + 'active' => false, + 'is_superuser' => true, + 'role' => 'admin', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000004', + 'username' => 'user-4', + 'email' => '4@example.com', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'FirstName4', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'token-4', + 'token_expires' => '2030-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'secret' => 'Lorem ipsum dolor sit amet', + 'secret_verified' => true, + 'is_superuser' => false, + 'tos_date' => '2015-06-24 17:33:54', + 'active' => true, + 'is_superuser' => false, + 'role' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000005', + 'username' => 'user-5', + 'email' => 'test@example.com', + 'password' => '12345', + 'first_name' => 'first-user-5', + 'last_name' => 'firts name 5', + 'token' => 'token-5', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => '', + 'activation_date' => '2015-06-24 17:33:54', + 'secret' => '', + 'secret_verified' => false, + 'tos_date' => '2015-06-24 17:33:54', + 'active' => true, + 'is_superuser' => false, + 'role' => 'user', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000006', + 'username' => 'user-6', + 'email' => '6@example.com', + 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', + 'first_name' => 'first-user-6', + 'last_name' => 'firts name 6', + 'token' => 'token-6', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => '', + 'activation_date' => '2015-06-24 17:33:54', + 'secret' => '', + 'secret_verified' => false, + 'tos_date' => '2015-06-24 17:33:54', + 'active' => true, + 'is_superuser' => false, + 'role' => 'user', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000007', + 'username' => 'Lorem ipsum dolor sit amet', + 'email' => 'Lorem ipsum dolor sit amet', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'Lorem ipsum dolor sit amet', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'secret' => 'Lorem ipsum dolor sit amet', + 'secret_verified' => false, + 'tos_date' => '2015-06-24 17:33:54', + 'active' => true, + 'is_superuser' => false, + 'role' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000008', + 'username' => 'Lorem ipsum dolor sit amet', + 'email' => 'Lorem ipsum dolor sit amet', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'Lorem ipsum dolor sit amet', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'secret' => 'Lorem ipsum dolor sit amet', + 'secret_verified' => false, + 'tos_date' => '2015-06-24 17:33:54', + 'active' => true, + 'is_superuser' => false, + 'role' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000009', + 'username' => 'Lorem ipsum dolor sit amet', + 'email' => 'Lorem ipsum dolor sit amet', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'Lorem ipsum dolor sit amet', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'secret' => 'Lorem ipsum dolor sit amet', + 'secret_verified' => false, + 'tos_date' => '2015-06-24 17:33:54', + 'active' => true, + 'is_superuser' => false, + 'role' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + [ + 'id' => '00000000-0000-0000-0000-000000000010', + 'username' => 'Lorem ipsum dolor sit amet', + 'email' => 'Lorem ipsum dolor sit amet', + 'password' => 'Lorem ipsum dolor sit amet', + 'first_name' => 'Lorem ipsum dolor sit amet', + 'last_name' => 'Lorem ipsum dolor sit amet', + 'token' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-06-24 17:33:54', + 'api_token' => 'Lorem ipsum dolor sit amet', + 'activation_date' => '2015-06-24 17:33:54', + 'secret' => 'Lorem ipsum dolor sit amet', + 'secret_verified' => false, + 'tos_date' => '2015-06-24 17:33:54', + 'active' => true, + 'is_superuser' => false, + 'role' => 'Lorem ipsum dolor sit amet', + 'created' => '2015-06-24 17:33:54', + 'modified' => '2015-06-24 17:33:54' + ], + ]; +} diff --git a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php new file mode 100644 index 000000000..6f6be7d8c --- /dev/null +++ b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php @@ -0,0 +1,67 @@ +assertFalse($Checker->isEnabled()); + + Configure::write('Users.GoogleAuthenticator.login', true); + $Checker = new DefaultTwoFactorAuthenticationChecker(); + $this->assertTrue($Checker->isEnabled()); + + Configure::delete('Users.GoogleAuthenticator.login'); + $Checker = new DefaultTwoFactorAuthenticationChecker(); + $this->assertTrue($Checker->isEnabled()); + } + + /** + * Test isRequired method + * + * @return void + */ + public function testIsRequired() + { + Configure::write('Users.GoogleAuthenticator.login', false); + $Checker = new DefaultTwoFactorAuthenticationChecker(); + $this->assertFalse($Checker->isRequired(['id' => 10])); + + Configure::write('Users.GoogleAuthenticator.login', true); + $Checker = new DefaultTwoFactorAuthenticationChecker(); + $this->assertTrue($Checker->isRequired(['id' => 10])); + + Configure::delete('Users.GoogleAuthenticator.login'); + $Checker = new DefaultTwoFactorAuthenticationChecker(); + $this->assertTrue($Checker->isRequired(['id' => 10])); + + $Checker = new DefaultTwoFactorAuthenticationChecker(); + $this->assertFalse($Checker->isRequired([])); + } +} diff --git a/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php b/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php new file mode 100644 index 000000000..5a44e7451 --- /dev/null +++ b/tests/TestCase/Auth/Exception/InvalidProviderExceptionTest.php @@ -0,0 +1,46 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php b/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php new file mode 100644 index 000000000..68d18bc24 --- /dev/null +++ b/tests/TestCase/Auth/Exception/InvalidSettingsExceptionTest.php @@ -0,0 +1,46 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php b/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php new file mode 100644 index 000000000..f182d9083 --- /dev/null +++ b/tests/TestCase/Auth/Exception/MissingEventListenerExceptionTest.php @@ -0,0 +1,45 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php b/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php new file mode 100644 index 000000000..e1eb1bb3d --- /dev/null +++ b/tests/TestCase/Auth/Exception/MissingProviderConfigurationExceptionTest.php @@ -0,0 +1,46 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Auth/Social/Mapper/FacebookTest.php b/tests/TestCase/Auth/Social/Mapper/FacebookTest.php new file mode 100644 index 000000000..8c8ba9e85 --- /dev/null +++ b/tests/TestCase/Auth/Social/Mapper/FacebookTest.php @@ -0,0 +1,91 @@ + 'test-token', + 'expires' => 1490988496 + ]); + $rawData = [ + 'token' => $token, + 'id' => '1', + 'name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@gmail.com', + 'hometown' => [ + 'id' => '108226049197930', + 'name' => 'Madrid' + ], + 'picture' => [ + 'data' => [ + 'url' => 'https://scontent.xx.fbcdn.net/v/test.jpg', + 'is_silhouette' => false + ] + ], + 'cover' => [ + 'source' => 'https://scontent.xx.fbcdn.net/v/test.jpg', + 'id' => '1' + ], + 'gender' => 'male', + 'locale' => 'en_US', + 'link' => 'https://www.facebook.com/app_scoped_user_id/1/', + 'timezone' => -5, + 'age_range' => [ + 'min' => 21 + ], + 'bio' => 'I am the best test user in the world.', + 'picture_url' => 'https://scontent.xx.fbcdn.net/v/test.jpg', + 'is_silhouette' => false, + 'cover_photo_url' => 'https://scontent.xx.fbcdn.net/v/test.jpg' + ]; + $providerMapper = new Facebook($rawData); + $user = $providerMapper(); + $this->assertEquals([ + 'id' => '1', + 'username' => null, + 'full_name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@gmail.com', + 'avatar' => 'https://graph.facebook.com/1/picture?type=large', + 'gender' => 'male', + 'link' => 'https://www.facebook.com/app_scoped_user_id/1/', + 'bio' => 'I am the best test user in the world.', + 'locale' => 'en_US', + 'validated' => true, + 'credentials' => [ + 'token' => 'test-token', + 'secret' => null, + 'expires' => 1490988496 + ], + 'raw' => $rawData + ], $user); + } +} diff --git a/tests/TestCase/Auth/Social/Mapper/GoogleTest.php b/tests/TestCase/Auth/Social/Mapper/GoogleTest.php new file mode 100644 index 000000000..376e8273a --- /dev/null +++ b/tests/TestCase/Auth/Social/Mapper/GoogleTest.php @@ -0,0 +1,73 @@ + 'test-token', + 'expires' => 1490988496 + ]); + $rawData = [ + 'token' => $token, + 'emails' => [['value' => 'test@gmail.com']], + 'id' => '1', + 'displayName' => 'Test User', + 'name' => [ + 'familyName' => 'User', + 'givenName' => 'Test' + ], + 'aboutMe' => 'I am the best test user in the world.', + 'url' => 'https://plus.google.com/+TestUser', + 'image' => [ + 'url' => 'https://lh3.googleusercontent.com/photo.jpg' + ] + ]; + $providerMapper = new Google($rawData); + $user = $providerMapper(); + $this->assertEquals([ + 'id' => '1', + 'username' => null, + 'full_name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@gmail.com', + 'avatar' => 'https://lh3.googleusercontent.com/photo.jpg', + 'gender' => null, + 'link' => 'https://plus.google.com/+TestUser', + 'bio' => 'I am the best test user in the world.', + 'locale' => null, + 'validated' => true, + 'credentials' => [ + 'token' => 'test-token', + 'secret' => null, + 'expires' => 1490988496 + ], + 'raw' => $rawData + ], $user); + } +} diff --git a/tests/TestCase/Auth/Social/Mapper/InstagramTest.php b/tests/TestCase/Auth/Social/Mapper/InstagramTest.php new file mode 100644 index 000000000..7d3b05625 --- /dev/null +++ b/tests/TestCase/Auth/Social/Mapper/InstagramTest.php @@ -0,0 +1,72 @@ + 'test-token', + 'expires' => 1490988496 + ]); + $rawData = [ + 'token' => $token, + 'profile_picture' => 'https://scontent-lax3-2.cdninstagram.com/test.jpg', + 'username' => 'test', + 'id' => '1', + 'full_name' => '', + 'website' => '', + 'counts' => [ + 'followed_by' => 35, + 'media' => 1, + 'follows' => 44 + ], + 'bio' => '' + ]; + $providerMapper = new Instagram($rawData); + $user = $providerMapper(); + $this->assertEquals([ + 'id' => '1', + 'username' => 'test', + 'full_name' => '', + 'first_name' => null, + 'last_name' => null, + 'email' => null, + 'avatar' => 'https://scontent-lax3-2.cdninstagram.com/test.jpg', + 'gender' => null, + 'link' => 'https://instagram.com/test', + 'bio' => '', + 'locale' => null, + 'validated' => false, + 'credentials' => [ + 'token' => 'test-token', + 'secret' => null, + 'expires' => 1490988496 + ], + 'raw' => $rawData + ], $user); + } +} diff --git a/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php b/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php new file mode 100644 index 000000000..3f17e77a7 --- /dev/null +++ b/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php @@ -0,0 +1,75 @@ + 'test-token', + 'expires' => 1490988496 + ]); + $rawData = [ + 'token' => $token, + 'emailAddress' => 'test@gmail.com', + 'firstName' => 'Test', + 'headline' => 'The best test user in the world.', + 'id' => '1', + 'industry' => 'Computer Software', + 'lastName' => 'User', + 'location' => [ + 'country' => [ + 'code' => 'es' + ], + 'name' => 'Spain' + ], + 'pictureUrl' => 'https://media.licdn.com/mpr/mprx/test.jpg', + 'publicProfileUrl' => 'https://www.linkedin.com/in/test' + ]; + $providerMapper = new LinkedIn($rawData); + $user = $providerMapper(); + $this->assertEquals([ + 'id' => '1', + 'username' => null, + 'full_name' => null, + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@gmail.com', + 'avatar' => 'https://media.licdn.com/mpr/mprx/test.jpg', + 'gender' => null, + 'link' => 'https://www.linkedin.com/in/test', + 'bio' => 'The best test user in the world.', + 'locale' => null, + 'validated' => true, + 'credentials' => [ + 'token' => 'test-token', + 'secret' => null, + 'expires' => 1490988496 + ], + 'raw' => $rawData + ], $user); + } +} diff --git a/tests/TestCase/Auth/Social/Mapper/TwitterTest.php b/tests/TestCase/Auth/Social/Mapper/TwitterTest.php new file mode 100644 index 000000000..d33aa343f --- /dev/null +++ b/tests/TestCase/Auth/Social/Mapper/TwitterTest.php @@ -0,0 +1,71 @@ + '1', + 'nickname' => 'test', + 'name' => 'Test User', + 'firstName' => null, + 'lastName' => null, + 'email' => null, + 'location' => '', + 'description' => '', + 'imageUrl' => 'http://pbs.twimg.com/profile_images/test.jpeg', + 'urls' => [], + 'extra' => [], + 'token' => [ + 'accessToken' => 'test-token', + 'tokenSecret' => 'test-secret' + ] + ]; + $providerMapper = new Twitter($rawData); + $user = $providerMapper(); + $this->assertEquals([ + 'id' => '1', + 'username' => 'test', + 'full_name' => 'Test User', + 'first_name' => null, + 'last_name' => null, + 'email' => null, + 'avatar' => 'http://pbs.twimg.com/profile_images/test.jpeg', + 'gender' => null, + 'link' => 'https://twitter.com/test', + 'bio' => '', + 'locale' => null, + 'validated' => false, + 'credentials' => [ + 'token' => 'test-token', + 'secret' => 'test-secret', + 'expires' => null + ], + 'raw' => $rawData + ], $user); + } +} diff --git a/tests/TestCase/Auth/SocialAuthenticateTest.php b/tests/TestCase/Auth/SocialAuthenticateTest.php new file mode 100644 index 000000000..14a5f72bb --- /dev/null +++ b/tests/TestCase/Auth/SocialAuthenticateTest.php @@ -0,0 +1,644 @@ +Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + + $this->Token = $this->getMockBuilder('League\OAuth2\Client\Token\AccessToken') + ->setMethods(['getToken', 'getExpires']) + ->disableOriginalConstructor() + ->getMock(); + + $this->controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(['failedSocialLogin', 'dispatchEvent']) + ->setConstructorArgs([$request, $response]) + ->getMock(); + + $this->controller->expects($this->any()) + ->method('dispatchEvent') + ->will($this->returnValue(new Event('test'))); + + $this->Request = $request; + $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', '_getProviderName', + '_mapUser', '_socialLogin', 'dispatchEvent', '_validateConfig', '_getController']); + + $this->SocialAuthenticate->expects($this->any()) + ->method('_getController') + ->will($this->returnValue($this->controller)); + } + + /** + * Tears down the fixture, for example, closes a network connection. + * This method is called after a test is executed. + */ + public function tearDown() + { + unset($this->SocialAuthenticate, $this->controller); + } + + protected function _getSocialAuthenticateMock() + { + return $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') + ->disableOriginalConstructor() + ->getMock(); + } + + protected function _getSocialAuthenticateMockMethods($methods) + { + return $this->getMockBuilder('CakeDC\Users\Auth\SocialAuthenticate') + ->disableOriginalConstructor() + ->setMethods($methods) + ->getMock(); + } + + /** + * test + * + * @expectedException \CakeDC\Users\Auth\Exception\MissingProviderConfigurationException + */ + public function testConstructorMissingConfig() + { + $socialAuthenticate = new SocialAuthenticate(new ComponentRegistry($this->controller)); + } + + /** + * test + * + */ + public function testConstructor() + { + $socialAuthenticate = new SocialAuthenticate(new ComponentRegistry($this->controller), [ + 'providers' => [ + 'facebook' => [ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => 'http://example.com/auth/facebook', + ] + ] + ] + ]); + + $this->assertInstanceOf('\CakeDC\Users\Auth\SocialAuthenticate', $socialAuthenticate); + } + + /** + * test + * + * @expectedException \CakeDC\Users\Auth\Exception\InvalidProviderException + */ + public function testConstructorMissingProvider() + { + $socialAuthenticate = new SocialAuthenticate(new ComponentRegistry($this->controller), [ + 'providers' => [ + 'facebook' => [ + 'className' => 'missing', + 'options' => [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => 'http://example.com/auth/facebook', + ] + ] + ] + ]); + } + + /** + * Test getUser + * + * @dataProvider providerGetUser + */ + public function testGetUserAuth($rawData, $mapper) + { + $user = $this->Table->get('00000000-0000-0000-0000-000000000002', ['contain' => ['SocialAccounts']]); + + $this->controller->expects($this->once()) + ->method('dispatchEvent') + ->with(UsersAuthComponent::EVENT_AFTER_REGISTER, compact('user')); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_authenticate') + ->with($this->Request) + ->will($this->returnValue($rawData)); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_getProviderName') + ->will($this->returnValue('facebook')); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_mapUser') + ->will($this->returnValue($mapper)); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_socialLogin') + ->will($this->returnValue($user)); + + $result = $this->SocialAuthenticate->getUser($this->Request); + $this->assertTrue($result['active']); + $this->assertEquals('00000000-0000-0000-0000-000000000002', $result['id']); + } + + /** + * Provider for getUser test method + * + */ + public function providerGetUser() + { + return [ + [ + 'rawData' => [ + 'token' => 'token', + 'id' => 'reference-2-1', + 'name' => 'User S', + 'first_name' => 'user', + 'last_name' => 'second', + 'email' => 'userSecond@example.com', + 'cover' => [ + 'id' => 'reference-2-1' + ], + 'gender' => 'female', + 'locale' => 'en_US', + 'link' => 'link', + ], + 'mappedData' => [ + 'id' => 'reference-2-1', + 'username' => null, + 'full_name' => 'User S', + 'first_name' => 'user', + 'last_name' => 'second', + 'email' => 'userSecond@example.com', + 'link' => 'link', + 'bio' => null, + 'locale' => 'en_US', + 'validated' => true, + 'credentials' => [ + 'token' => 'token', + 'secret' => null, + 'expires' => 1458423682 + ], + 'raw' => [ + + ], + 'provider' => 'Facebook' + ], + ] + + ]; + } + + /** + * Test getUser + * + */ + public function testGetUserSessionData() + { + $user = ['username' => 'username', 'email' => 'myemail@test.com']; + $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', + '_getProviderName', '_mapUser', '_touch', '_validateConfig']); + + $session = $this->getMockBuilder('Cake\Http\Session') + ->setMethods(['read', 'delete']) + ->getMock(); + $session->expects($this->once()) + ->method('read') + ->with('Users.social') + ->will($this->returnValue($user)); + + $session->expects($this->once()) + ->method('delete') + ->with('Users.social'); + + $this->Request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['getSession']) + ->getMock(); + $this->Request->expects($this->any()) + ->method('getSession') + ->will($this->returnValue($session)); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_touch') + ->will($this->returnValue($user)); + + $this->SocialAuthenticate->getUser($this->Request); + } + + /** + * Test getUser + * + * @dataProvider providerGetUser + */ + public function testGetUserNotEmailProvided($rawData, $mapper) + { + $this->SocialAuthenticate->expects($this->once()) + ->method('_authenticate') + ->with($this->Request) + ->will($this->returnValue($rawData)); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_getProviderName') + ->will($this->returnValue('facebook')); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_mapUser') + ->will($this->returnValue($mapper)); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_socialLogin') + ->will($this->throwException(new MissingEmailException('missing email'))); + + $this->controller->expects($this->once()) + ->method('dispatchEvent') + ->with(UsersAuthComponent::EVENT_FAILED_SOCIAL_LOGIN); + + $this->controller->expects($this->once()) + ->method('failedSocialLogin'); + + $this->SocialAuthenticate->getUser($this->Request); + } + + /** + * Test getUser + * + * @dataProvider providerGetUser + */ + public function testGetUserNotActive($rawData, $mapper) + { + $this->SocialAuthenticate->expects($this->once()) + ->method('_authenticate') + ->with($this->Request) + ->will($this->returnValue($rawData)); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_getProviderName') + ->will($this->returnValue('facebook')); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_mapUser') + ->will($this->returnValue($mapper)); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_socialLogin') + ->will($this->throwException(new UserNotActiveException('user not active'))); + + $this->SocialAuthenticate->getUser($this->Request); + } + + /** + * Test getUser + * + * @dataProvider providerGetUser + */ + public function testGetUserNotActiveAccount($rawData, $mapper) + { + $this->SocialAuthenticate->expects($this->once()) + ->method('_authenticate') + ->with($this->Request) + ->will($this->returnValue($rawData)); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_getProviderName') + ->will($this->returnValue('facebook')); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_mapUser') + ->will($this->returnValue($mapper)); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_socialLogin') + ->will($this->throwException(new AccountNotActiveException('user not active'))); + + $this->SocialAuthenticate->getUser($this->Request); + } + + /** + * Test getUser + * + * @dataProvider providerTwitter + */ + public function testGetUserNotEmailProvidedTwitter($rawData, $mapper) + { + $this->SocialAuthenticate->expects($this->once()) + ->method('_authenticate') + ->with($this->Request) + ->will($this->returnValue($rawData)); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_getProviderName') + ->will($this->returnValue('twitter')); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_mapUser') + ->will($this->returnValue($mapper)); + + $this->SocialAuthenticate->expects($this->once()) + ->method('_socialLogin') + ->will($this->throwException(new MissingEmailException('missing email'))); + + $this->SocialAuthenticate->getUser($this->Request); + } + + /** + * Provider for getUser test method + * + */ + public function providerTwitter() + { + return [ + [ + 'rawData' => [ + 'token' => 'token', + 'id' => 'reference-2-1', + 'name' => 'User S', + 'first_name' => 'user', + 'last_name' => 'second', + 'email' => 'userSecond@example.com', + 'cover' => [ + 'id' => 'reference-2-1' + ], + 'gender' => 'female', + 'locale' => 'en_US', + 'link' => 'link', + ], + 'mappedData' => [ + 'id' => 'reference-2-1', + 'username' => null, + 'full_name' => 'User S', + 'first_name' => 'user', + 'last_name' => 'second', + 'email' => 'userSecond@example.com', + 'link' => 'link', + 'bio' => null, + 'locale' => 'en_US', + 'validated' => true, + 'credentials' => [ + 'token' => 'token', + 'secret' => null, + 'expires' => 1458423682 + ], + 'raw' => [ + + ], + 'provider' => 'Twitter' + ], + ] + + ]; + } + + /** + * Test _socialLogin + * + * @dataProvider providerMapper + */ + public function testSocialLogin() + { + $this->SocialAuthenticate = $this->_getSocialAuthenticateMock(); + + $reflectedClass = new ReflectionClass($this->SocialAuthenticate); + $socialLogin = $reflectedClass->getMethod('_socialLogin'); + $socialLogin->setAccessible(true); + $data = [ + 'id' => 'reference-2-1', + 'provider' => 'Facebook' + ]; + $result = $socialLogin->invoke($this->SocialAuthenticate, $data); + $this->assertEquals($result->id, '00000000-0000-0000-0000-000000000002'); + $this->assertTrue($result->active); + } + + /** + * Test _mapUser + * + * @dataProvider providerMapper + */ + public function testMapUser($data, $mappedData) + { + $data['token'] = $this->Token; + $this->SocialAuthenticate = $this->_getSocialAuthenticateMock(); + + $reflectedClass = new ReflectionClass($this->SocialAuthenticate); + $mapUser = $reflectedClass->getMethod('_mapUser'); + $mapUser->setAccessible(true); + + $this->Token->expects($this->once()) + ->method('getToken') + ->will($this->returnValue('token')); + + $this->Token->expects($this->once()) + ->method('getExpires') + ->will($this->returnValue(1458510952)); + + $result = $mapUser->invoke($this->SocialAuthenticate, 'Facebook', $data); + unset($result['raw']); + $this->assertEquals($mappedData, $result); + } + + /** + * Provider for _mapUser test method + * + */ + public function providerMapper() + { + return [ + [ + 'rawData' => [ + 'id' => 'my-facebook-id', + 'name' => 'My name.', + 'first_name' => 'My first name', + 'last_name' => 'My lastname.', + 'email' => 'myemail@example.com', + 'gender' => 'female', + 'locale' => 'en_US', + 'link' => 'https://www.facebook.com/app_scoped_user_id/my-facebook-id/', + ], + 'mappedData' => [ + 'id' => 'my-facebook-id', + 'username' => null, + 'full_name' => 'My name.', + 'first_name' => 'My first name', + 'last_name' => 'My lastname.', + 'email' => 'myemail@example.com', + 'avatar' => 'https://graph.facebook.com/my-facebook-id/picture?type=large', + 'gender' => 'female', + 'link' => 'https://www.facebook.com/app_scoped_user_id/my-facebook-id/', + 'bio' => null, + 'locale' => 'en_US', + 'validated' => true, + 'credentials' => [ + 'token' => 'token', + 'secret' => null, + 'expires' => (int)1458510952 + ], + 'provider' => 'Facebook' + ], + ] + + ]; + } + + /** + * Test _mapUser + * + * @expectedException CakeDC\Users\Exception\MissingProviderException + */ + public function testMapUserException() + { + $data = []; + $this->SocialAuthenticate = $this->_getSocialAuthenticateMock(); + + $reflectedClass = new ReflectionClass($this->SocialAuthenticate); + $mapUser = $reflectedClass->getMethod('_mapUser'); + $mapUser->setAccessible(true); + $mapUser->invoke($this->SocialAuthenticate, null, $data); + } + + /** + * Provider for normalizeConfig test method + * + * @dataProvider providers + */ + public function testNormalizeConfig($data, $oauth2, $callTimes, $enabledNoOAuth2Provider) + { + Configure::write('OAuth2', $oauth2); + $this->SocialAuthenticate = $this->_getSocialAuthenticateMockMethods(['_authenticate', + '_getProviderName', '_mapUser', '_touch', '_validateConfig', '_normalizeConfig']); + + $this->SocialAuthenticate->expects($this->exactly($callTimes)) + ->method('_normalizeConfig'); + + $this->SocialAuthenticate->normalizeConfig($data, $enabledNoOAuth2Provider); + } + + /** + * Test normalizeConfig + * + * @expectedException CakeDC\Users\Auth\Exception\MissingProviderConfigurationException + */ + public function testNormalizeConfigException() + { + $this->SocialAuthenticate->normalizeConfig([]); + } + + /** + * Provider for normalizeConfig test method + * + */ + public function providers() + { + return [ + [ + [ + 'providers' => [ + 'facebook' => [ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + ], + 'instagram' => [ + 'className' => 'League\OAuth2\Client\Provider\Instagram', + ] + ], + + ], + [ + 'providers' => [ + 'facebook' => [ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + ], + 'instagram' => [ + 'className' => 'League\OAuth2\Client\Provider\Instagram', + ] + ] + ], + 2, + false + ], + [ + [ + 'providers' => [ + 'facebook' => [ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + ], + ], + + ], + [ + 'providers' => [ + 'facebook' => [ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + ], + ] + ], + 1, + false + ], + [ + [ + 'providers' => [ + 'facebook' => [ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + ], + ], + + ], + [ + 'providers' => [ + 'instagram' => [ + 'className' => 'League\OAuth2\Client\Provider\Instagram', + ] + ] + ], + 2, + false + ], + [ + [], + [], + 0, + true + ] + ]; + } +} diff --git a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php new file mode 100644 index 000000000..4c4908028 --- /dev/null +++ b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php @@ -0,0 +1,44 @@ +build(); + $this->assertInstanceOf(DefaultTwoFactorAuthenticationChecker::class, $result); + } + + /** + * Test getChecker method + * + * @return void + */ + public function testGetCheckerInvalidInterface() + { + Configure::write('GoogleAuthenticator.checker', 'stdClass'); + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage("Invalid config for 'GoogleAuthenticator.checker', 'stdClass' does not implement 'CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface'"); + $result = (new TwoFactorAuthenticationCheckerFactory())->build(); + } +} diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php new file mode 100644 index 000000000..367326745 --- /dev/null +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -0,0 +1,136 @@ +backupUsersConfig = Configure::read('Users'); + + Router::reload(); + Router::connect('/route/*', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword' + ]); + Router::connect('/notAllowed/*', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'edit' + ]); + + Security::setSalt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); + Configure::write('App.namespace', 'Users'); + Configure::write('Users.GoogleAuthenticator.login', true); + + $this->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is', 'method']) + ->getMock(); + $this->request->expects($this->any())->method('is')->will($this->returnValue(true)); + $this->response = $this->getMockBuilder('Cake\Http\Response') + ->setMethods(['stop']) + ->getMock(); + $this->Controller = new Controller($this->request, $this->response); + $this->Registry = $this->Controller->components(); + $this->Controller->GoogleAuthenticator = new GoogleAuthenticatorComponent($this->Registry); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + + $_SESSION = []; + unset($this->Controller, $this->GoogleAuthenticator); + Configure::write('Users', $this->backupUsersConfig); + Configure::write('Users.GoogleAuthenticator.login', false); + } + + /** + * Test initialize + * + */ + public function testInitialize() + { + $this->Controller->GoogleAuthenticator = new GoogleAuthenticatorComponent($this->Registry); + $this->assertInstanceOf('CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent', $this->Controller->GoogleAuthenticator); + } + + /** + * test base64 qr-code returned from component + * @return void + */ + public function testgetQRCodeImageAsDataUri() + { + $this->Controller->GoogleAuthenticator->initialize([]); + $result = $this->Controller->GoogleAuthenticator->getQRCodeImageAsDataUri('test@localhost.com', '123123'); + + $this->assertContains('data:image/png;base64', $result); + } + + /** + * Making sure we return secret + * @return void + */ + public function testCreateSecret() + { + $this->Controller->GoogleAuthenticator->initialize([]); + $result = $this->Controller->GoogleAuthenticator->createSecret(); + $this->assertNotEmpty($result); + } + + /** + * Testing code verification in the component + * @return void + */ + public function testVerifyCode() + { + $this->Controller->GoogleAuthenticator->initialize([]); + $secret = $this->Controller->GoogleAuthenticator->createSecret(); + $verificationCode = $this->Controller->GoogleAuthenticator->tfa->getCode($secret); + + $verified = $this->Controller->GoogleAuthenticator->verifyCode($secret, $verificationCode); + $this->assertTrue($verified); + } +} diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php new file mode 100644 index 000000000..e6b117686 --- /dev/null +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -0,0 +1,194 @@ +request = new ServerRequest('controller_posts/index'); + $this->request = $this->request->withParam('pass', []); + $this->controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(['redirect']) + ->setConstructorArgs([$this->request]) + ->getMock(); + $this->registry = new ComponentRegistry($this->controller); + $this->rememberMeComponent = new RememberMeComponent($this->registry, []); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + unset($this->rememberMeComponent); + + parent::tearDown(); + } + + /** + * Test initialize method + * + * @return void + */ + public function testInitialize() + { + $cookieOptions = [ + 'expires' => '1 month', + 'httpOnly' => true, + 'path' => '', + 'domain' => '', + 'secure' => false, + 'key' => '2a20bac195a9eb2e28f05b7ac7090afe599365a8fe480b7d8a5ce0f79687346e', + 'encryption' => 'aes', + 'enabled' => false + ]; + $this->assertEquals($cookieOptions, $this->rememberMeComponent->Cookie->configKey('remember_me')); + } + + /** + * Test initialize method + * + * @return void + */ + public function testInitializeException() + { + $salt = Security::getSalt(); + Security::setSalt('too small'); + try { + $this->rememberMeComponent = new RememberMeComponent($this->registry, []); + } catch (InvalidArgumentException $ex) { + $this->assertEquals('Invalid app salt, app salt must be at least 256 bits (32 bytes) long', $ex->getMessage()); + } + + Security::setSalt($salt); + } + + /** + * Test + * + * @return void + */ + public function testSetLoginCookie() + { + $event = new Event('event'); + $this->rememberMeComponent->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user']) + ->disableOriginalConstructor() + ->getMock(); + $this->rememberMeComponent->Auth->expects($this->once()) + ->method('user') + ->with('id') + ->will($this->returnValue(1)); + $this->rememberMeComponent->Cookie = $this->getMockBuilder('Cake\Controller\Component\CookieComponent') + ->setMethods(['write']) + ->disableOriginalConstructor() + ->getMock(); + $this->rememberMeComponent->request = (new ServerRequest('/'))->withEnv('HTTP_USER_AGENT', 'user-agent') + ->withData(Configure::read('Users.Key.Data.rememberMe'), '1'); + $this->rememberMeComponent->Cookie->expects($this->once()) + ->method('write') + ->with('remember_me', ['id' => 1, 'user_agent' => 'user-agent']); + $this->rememberMeComponent->setLoginCookie($event); + } + + /** + * Test + * + * @return void + */ + public function testBeforeFilter() + { + $event = new Event('event'); + $this->rememberMeComponent->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $this->rememberMeComponent->Auth->expects($this->once()) + ->method('user'); + $user = ['id' => 1]; + $this->rememberMeComponent->Auth->expects($this->once()) + ->method('identify') + ->will($this->returnValue($user)); + $this->rememberMeComponent->Auth->expects($this->once()) + ->method('setUser') + ->with($user); + $this->controller->expects($this->once()) + ->method('redirect') + ->with('/controller_posts/index'); + $this->rememberMeComponent->beforeFilter($event); + } + + /** + * Test + * + * @return void + */ + public function testBeforeFilterNotIdentified() + { + $event = new Event('event'); + $this->rememberMeComponent->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $this->rememberMeComponent->Auth->expects($this->at(0)) + ->method('user'); + $this->rememberMeComponent->Auth->expects($this->at(1)) + ->method('identify'); + + $this->assertNull($this->rememberMeComponent->beforeFilter($event)); + } + + /** + * Test + * + * @return void + */ + public function testBeforeFilterUserLoggedIn() + { + $event = new Event('event'); + $this->rememberMeComponent->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $this->rememberMeComponent->Auth->expects($this->once()) + ->method('user') + ->will($this->returnValue([ + 'id' => 1, + ])); + $this->assertNull($this->rememberMeComponent->beforeFilter($event)); + } +} diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php new file mode 100644 index 000000000..7860d3439 --- /dev/null +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -0,0 +1,515 @@ +backupUsersConfig = Configure::read('Users'); + + Router::reload(); + Router::connect('/route/*', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword' + ]); + Router::connect('/notAllowed/*', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'edit' + ]); + Security::setSalt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); + Configure::write('App.namespace', 'Users'); + $this->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is', 'method']) + ->getMock(); + $this->request->expects($this->any())->method('is')->will($this->returnValue(true)); + $this->response = $this->getMockBuilder('Cake\Http\Response') + ->setMethods(['stop']) + ->getMock(); + $this->Controller = new Controller($this->request, $this->response); + $this->Controller->setName('Users'); + $this->Registry = $this->Controller->components(); + $this->Controller->UsersAuth = new UsersAuthComponent($this->Registry); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + + $_SESSION = []; + unset($this->Controller, $this->UsersAuth); + Configure::write('Users', $this->backupUsersConfig); + } + + /** + * Test initialize + * + */ + public function testInitialize() + { + $this->Registry->unload('Auth'); + $this->Controller->UsersAuth = new UsersAuthComponent($this->Registry); + $this->assertInstanceOf('CakeDC\Users\Controller\Component\UsersAuthComponent', $this->Controller->UsersAuth); + } + + /** + * Test initialize with not rememberMe component needed + * + */ + public function testInitializeNoRequiredRememberMe() + { + Configure::write('Users.RememberMe.active', false); + $class = 'CakeDC\Users\Controller\Component\UsersAuthComponent'; + $this->Controller->UsersAuth = $this->getMockBuilder($class) + ->setMethods(['_loadRememberMe', '_initAuth', '_loadSocialLogin', '_attachPermissionChecker']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->UsersAuth->expects($this->once()) + ->method('_initAuth'); + $this->Controller->UsersAuth->expects($this->never()) + ->method('_loadRememberMe'); + $this->Controller->UsersAuth->initialize([]); + } + + /** + * test + * + * @return void + */ + public function testIsUrlAuthorizedUserNotLoggedIn() + { + $event = new Event('event'); + $event->setData([ + 'url' => '/route', + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->expects($this->once()) + ->method('user') + ->will($this->returnValue(false)); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertFalse($result); + } + + /** + * test The user is not logged in, but the controller action is public $this->Auth->allow() + * + * @return void + */ + public function testIsUrlAuthorizedUserNotLoggedInActionAllowed() + { + $event = new Event('event'); + $event->setData([ + 'url' => '/route', + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->allowedActions = ['requestResetPassword']; + $this->Controller->Auth->expects($this->never()) + ->method('user'); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } + + /** + * test The user is logged in and not allowed by rules to access this action, + * but the controller action is public $this->Auth->allow() + * + * @return void + */ + public function testIsUrlAuthorizedUserLoggedInNotAllowedActionAllowed() + { + $event = new Event('event'); + $event->setData([ + 'url' => '/notAllowed', + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->allowedActions = ['edit']; + $this->Controller->Auth->expects($this->never()) + ->method('user'); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } + + /** + * test The user is logged in and allowed by rules to access this action, + * and the controller action is public $this->Auth->allow() + * + * @return void + */ + public function testIsUrlAuthorizedUserLoggedInAllowedActionAllowed() + { + $event = new Event('event'); + $event->setData([ + 'url' => '/route', + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->allowedActions = ['requestResetPassword']; + $this->Controller->Auth->expects($this->never()) + ->method('user'); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } + + /** + * test + * + * @return void + */ + public function testIsUrlAuthorizedNoUrl() + { + $event = new Event('event'); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertFalse($result); + } + + /** + * test + * + * @return void + */ + public function testIsUrlAuthorizedUrlRelativeString() + { + $event = new Event('event'); + $event->setData([ + 'url' => '/route', + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->expects($this->once()) + ->method('user') + ->will($this->returnValue(['id' => 1])); + $this->Controller->Auth->expects($this->once()) + ->method('isAuthorized') + ->with(null, $this->callback(function ($subject) { + return $subject->getAttribute('params') === [ + 'pass' => [], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; + })) + ->will($this->returnValue(true)); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } + + /** + * test + * + * @return void + * @expectedException \Cake\Routing\Exception\MissingRouteException + */ + public function testIsUrlAuthorizedMissingRouteString() + { + $event = new Event('event'); + $event->setData([ + 'url' => '/missingRoute', + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->expects($this->never()) + ->method('user'); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + } + + /** + * test + * + * @return void + * @expectedException \Cake\Routing\Exception\MissingRouteException + */ + public function testIsUrlAuthorizedMissingRouteArray() + { + $event = new Event('event'); + $event->setData([ + 'url' => [ + 'controller' => 'missing', + 'action' => 'missing', + ], + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->expects($this->never()) + ->method('user'); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + } + + /** + * test + * + * @return void + */ + public function testIsUrlAuthorizedUrlAbsoluteForCurrentAppString() + { + $event = new Event('event'); + $event->setData([ + 'url' => Router::fullBaseUrl() . '/route', + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->expects($this->once()) + ->method('user') + ->will($this->returnValue(['id' => 1])); + $this->Controller->Auth->expects($this->once()) + ->method('isAuthorized') + ->with(null, $this->callback(function ($subject) { + return $subject->getAttribute('params') === [ + 'pass' => [], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; + })) + ->will($this->returnValue(true)); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } + + /** + * test + * + * @return void + */ + public function testIsUrlAuthorizedUrlRelativeForCurrentAppString() + { + $event = new Event('event'); + $event->setData([ + 'url' => 'route', + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->expects($this->once()) + ->method('user') + ->will($this->returnValue(['id' => 1])); + $this->Controller->Auth->expects($this->once()) + ->method('isAuthorized') + ->with(null, $this->callback(function ($subject) { + return $subject->getAttribute('params') === [ + 'pass' => [], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; + })) + ->will($this->returnValue(true)); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } + + /** + * + * + * @return void + */ + public function testIsUrlAuthorizedUrlAbsoluteForOtherAppString() + { + $event = new Event('event'); + $event->setData([ + 'url' => 'http://example.com', + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->expects($this->never()) + ->method('user'); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } + + /** + * test + * + * @return void + */ + public function testIsUrlAuthorizedUrlArray() + { + $event = new Event('event'); + $event->setData([ + 'url' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + 'pass-one' + ], + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->expects($this->once()) + ->method('user') + ->will($this->returnValue(['id' => 1])); + $this->Controller->Auth->expects($this->once()) + ->method('isAuthorized') + ->with(null, $this->callback(function ($subject) { + return $subject->getAttribute('params') === [ + 'pass' => ['pass-one'], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; + })) + ->will($this->returnValue(true)); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } + + /** + * When application is installed using a base folder, we need to ensure array routes are + * normalized too to remove the base from the url used for matching the rules + * + * @see https://github.com/CakeDC/users/issues/538 + * + * @return void + */ + public function testIsUrlAuthorizedBaseUrl() + { + Configure::write('App.base', 'app'); + Router::pushRequest(new ServerRequest([ + 'base' => '/app', + 'url' => '/', + ])); + $event = new Event('event'); + $event->setData([ + 'url' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + ], + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->expects($this->once()) + ->method('user') + ->will($this->returnValue(['id' => 1])); + $this->Controller->Auth->expects($this->once()) + ->method('isAuthorized') + ->with(null, $this->callback(function ($subject) { + return $subject->getAttribute('params') === [ + 'pass' => [], + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'requestResetPassword', + '_matchedRoute' => '/route/*', + ]; + })) + ->will($this->returnValue(true)); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertTrue($result); + } + /** + * test The user is logged in and allowed by rules to access this action, + * and we are checking another controller action not allowed + * + * this case would prevent permissions checked for allowed actions in another controller + * @see https://github.com/CakeDC/users/issues/527 for a workaround if you need to + * check allowed on another controller + * + * @return void + */ + public function testIsUrlAuthorizedUserLoggedInAllowedActionAllowedAnotherController() + { + Router::connect('/route-another-controller/*', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'AnotherController', + 'action' => 'requestResetPassword' + ]); + $event = new Event('event'); + $event->setData([ + 'url' => '/route-another-controller', + ]); + $this->Controller->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'isAuthorized']) + ->disableOriginalConstructor() + ->getMock(); + $this->Controller->Auth->allowedActions = ['requestResetPassword']; + $this->Controller->Auth->expects($this->once()) + ->method('user') + ->will($this->returnValue(false)); + $result = $this->Controller->UsersAuth->isUrlAuthorized($event); + $this->assertFalse($result); + } +} diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php new file mode 100644 index 000000000..296f15f2f --- /dev/null +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -0,0 +1,204 @@ +configOpauth = Configure::read('Opauth'); + $this->configRememberMe = Configure::read('Users.RememberMe.active'); + Configure::write('Opauth', null); + Configure::write('Users.RememberMe.active', false); + + Email::setConfigTransport('test', [ + 'className' => 'Debug' + ]); + $this->configEmail = Email::getConfig('default'); + Email::drop('default'); + Email::setConfig('default', [ + 'transport' => 'test', + 'from' => 'cakedc@example.com' + ]); + + $request = new ServerRequest('/users/users/index'); + $request = $request->withParam('plugin', 'CakeDC/Users'); + + $this->Controller = $this->getMockBuilder('CakeDC\Users\Controller\SocialAccountsController') + ->setMethods(['redirect', 'render']) + ->setConstructorArgs([$request, null, 'SocialAccounts']) + ->getMock(); + $this->Controller->SocialAccounts = $this->getMockForModel('CakeDC\Users.SocialAccounts', ['sendSocialValidationEmail'], [ + 'className' => 'CakeDC\Users\Model\Table\SocialAccountsTable' + ]); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + Email::drop('default'); + Email::dropTransport('test'); + //Email::setConfig('default', $this->configEmail); + + Configure::write('Opauth', $this->configOpauth); + Configure::write('Users.RememberMe.active', $this->configRememberMe); + + parent::tearDown(); + } + + /** + * test + * + * @return void + */ + public function testValidateAccountHappy() + { + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $this->Controller->validateAccount('Facebook', 'reference-1-1234', 'token-1234'); + $this->assertEquals('Account validated successfully', $this->Controller->request->getSession()->read('Flash.flash.0.message')); + } + + /** + * test + * + * @return void + */ + public function testValidateAccountInvalidToken() + { + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $this->Controller->validateAccount('Facebook', 'reference-1-1234', 'token-not-found'); + $this->assertEquals('Invalid token and/or social account', $this->Controller->request->getSession()->read('Flash.flash.0.message')); + } + + /** + * test + * + * @return void + */ + public function testValidateAccountAlreadyActive() + { + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); + $this->assertEquals('Social Account already active', $this->Controller->request->getSession()->read('Flash.flash.0.message')); + } + + /** + * test + * + * @return void + */ + public function testResendValidationHappy() + { + $behaviorMock = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialAccountBehavior') + ->setMethods(['sendSocialValidationEmail']) + ->setConstructorArgs([$this->Controller->SocialAccounts]) + ->getMock(); + $this->Controller->SocialAccounts->behaviors()->set('SocialAccount', $behaviorMock); + $behaviorMock->expects($this->once()) + ->method('sendSocialValidationEmail') + ->will($this->returnValue(true)); + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + + $this->Controller->resendValidation('Facebook', 'reference-1-1234'); + $this->assertEquals('Email sent successfully', $this->Controller->request->getSession()->read('Flash.flash.0.message')); + } + + /** + * test + * + * @return void + */ + public function testResendValidationEmailError() + { + $behaviorMock = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialAccountBehavior') + ->setMethods(['sendSocialValidationEmail']) + ->setConstructorArgs([$this->Controller->SocialAccounts]) + ->getMock(); + $this->Controller->SocialAccounts->behaviors()->set('SocialAccount', $behaviorMock); + $behaviorMock->expects($this->once()) + ->method('sendSocialValidationEmail') + ->will($this->returnValue(false)); + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + + $this->Controller->resendValidation('Facebook', 'reference-1-1234'); + $this->assertEquals('Email could not be sent', $this->Controller->request->getSession()->read('Flash.flash.0.message')); + } + + /** + * test + * + * @return void + */ + public function testResendValidationInvalid() + { + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $this->Controller->resendValidation('Facebook', 'reference-invalid'); + $this->assertEquals('Invalid account', $this->Controller->request->getSession()->read('Flash.flash.0.message')); + } + + /** + * test + * + * @return void + */ + public function testResendValidationAlreadyActive() + { + $this->Controller->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); + $this->assertEquals('Social Account already active', $this->Controller->request->getSession()->read('Flash.flash.0.message')); + } +} diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php new file mode 100644 index 000000000..6cc88cc19 --- /dev/null +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -0,0 +1,220 @@ +traitMockMethods)); + $this->table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + try { + $this->Trait = $this->getMockBuilder($this->traitClassName) + ->setMethods($traitMockMethods) + ->getMockForTrait(); + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($this->table)); + } catch (PHPUnit_Framework_MockObject_RuntimeException $ex) { + debug($ex); + $this->fail("Unit tests extending BaseTraitTest should declare the trait class name in the \$traitClassName variable before calling setUp()"); + } + + if ($this->mockDefaultEmail) { + Email::setConfigTransport('test', [ + 'className' => 'Debug' + ]); + $this->configEmail = Email::getConfig('default'); + Email::drop('default'); + Email::setConfig('default', [ + 'transport' => 'test', + 'from' => 'cakedc@example.com' + ]); + } + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->table, $this->Trait); + if ($this->mockDefaultEmail) { + Email::drop('default'); + Email::dropTransport('test'); + //Email::setConfig('default', $this->setConfigEmail); + } + parent::tearDown(); + } + + /** + * Mock session and mock session attributes + * + * @return void + */ + protected function _mockSession($attributes) + { + $session = new \Cake\Http\Session(); + + foreach ($attributes as $field => $value) { + $session->write($field, $value); + } + + $this->Trait->request + ->expects($this->any()) + ->method('session') + ->willReturn($session); + } + + /** + * mock request for GET + * + * @return void + */ + protected function _mockRequestGet($withSession = false) + { + $methods = ['is', 'referer', 'getData']; + + if ($withSession) { + $methods[] = 'session'; + } + + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->setMethods($methods) + ->getMock(); + $this->Trait->request->expects($this->any()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + } + + /** + * mock Flash Component + * + * @return void + */ + protected function _mockFlash() + { + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['error', 'success']) + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * mock Request for POST, is and allow methods + * + * @param mixed $with used in with + * @return void + */ + protected function _mockRequestPost($with = 'post') + { + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->setMethods(['is', 'getData', 'allow']) + ->getMock(); + $this->Trait->request->expects($this->any()) + ->method('is') + ->with($with) + ->will($this->returnValue(true)); + } + + /** + * Mock Auth and retur user id 1 + * + * @return void + */ + protected function _mockAuthLoggedIn($user = []) + { + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $user += [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'password' => '12345', + ]; + $this->Trait->Auth->expects($this->any()) + ->method('identify') + ->will($this->returnValue($user)); + $this->Trait->Auth->expects($this->any()) + ->method('user') + ->with('id') + ->will($this->returnValue($user['id'])); + } + + /** + * Mock the Auth component + * + * @return void + */ + protected function _mockAuth() + { + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * mock utility + * + * @param Event $event event + * @param array $result array of data + * @return void + */ + protected function _mockDispatchEvent(Event $event = null, $result = []) + { + if (is_null($event)) { + $event = new Event('cool-name-here'); + } + + if (!empty($result)) { + $event->result = new Entity($result); + } + $this->Trait->expects($this->any()) + ->method('dispatchEvent') + ->will($this->returnValue($event)); + } +} diff --git a/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php new file mode 100644 index 000000000..3511fd9a5 --- /dev/null +++ b/tests/TestCase/Controller/Traits/CustomUsersTableTraitTest.php @@ -0,0 +1,41 @@ +controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(['header', 'redirect', 'render', '_stop']) + ->getMock(); + $this->controller->Trait = $this->getMockForTrait('CakeDC\Users\Controller\Traits\CustomUsersTableTrait'); + } + + public function tearDown() + { + parent::tearDown(); + } + + public function testGetUsersTable() + { + $table = $this->controller->Trait->getUsersTable(); + $this->assertEquals('CakeDC/Users.Users', $table->getRegistryAlias()); + $newTable = new Table(); + $this->controller->Trait->setUsersTable($newTable); + $this->assertSame($newTable, $this->controller->Trait->getUsersTable()); + } +} diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php new file mode 100644 index 000000000..00ce7b11b --- /dev/null +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -0,0 +1,825 @@ +oauthConfig === null) { + $this->oauthConfig = Configure::read('OAuth'); + } + $this->traitClassName = 'CakeDC\Users\Controller\Traits\LinkSocialTrait'; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; + + parent::setUp(); + $request = new ServerRequest(); + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set']) + ->getMockForTrait(); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->Trait->request = $request; + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + Configure::write('OAuth', $this->oauthConfig); + parent::tearDown(); + } + + /** + * mock request for GET + * + * @return void + */ + protected function _mockRequestGet($withSession = false) + { + $methods = ['is', 'referer', 'getData', 'getQuery', 'getQueryParams']; + + if ($withSession) { + $methods[] = 'session'; + } + + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods($methods) + ->getMock(); + $this->Trait->request->expects($this->any()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + } + + /** + * test linkSocial method + * + * @return void + */ + public function testLinkSocialHappy() + { + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->_mockRequestGet(true); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->_mockSession([]); + $this->Trait->Flash->expects($this->never()) + ->method('error'); + + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAuthorizationUrl', 'getState']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->once()) + ->method('getAuthorizationUrl') + ->will($this->returnValue('http://localhost/fake/facebook/login')); + + $ProviderMock->expects($this->once()) + ->method('getState') + ->will($this->returnValue('a3423ja9ads90u3242309')); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' + ] + ]) + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->expects($this->once()) + ->method('redirect') + ->with( + $this->equalTo('http://localhost/fake/facebook/login') + ); + + $this->Trait->linkSocial('facebook'); + } + + /** + * test + * + * @return void + */ + public function testLinkSocialNotDefineLinkSocialRedirectUri() + { + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + Configure::delete('OAuth.providers.facebook.options.callbackLinkSocialUri'); + + $result = false; + try { + $this->_mockRequestGet(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + + $this->_mockDispatchEvent(new Event('event')); + + $this->Trait->linkSocial('facebook'); + } catch (NotFoundException $e) { + $result = true; + } + $this->assertTrue($result); + } + + /** + * test + * + * @return void + */ + public function testLinkSocialNotDefinedClientId() + { + Configure::delete('OAuth.providers.facebook.options.clientId'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + $result = false; + try { + $this->_mockRequestGet(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + + $this->_mockDispatchEvent(new Event('event')); + + $this->Trait->linkSocial('facebook'); + } catch (NotFoundException $e) { + $result = true; + } + $this->assertTrue($result); + } + + /** + * test + * + * @return void + */ + public function testLinkSocialNotDefinedClientSecret() + { + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::delete('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + $result = false; + try { + $this->_mockRequestGet(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + + $this->_mockDispatchEvent(new Event('event')); + + $this->Trait->linkSocial('facebook'); + } catch (NotFoundException $e) { + $result = true; + } + $this->assertTrue($result); + } + + /** + * test + * + * @return void + */ + public function testCallbackLinkSocialHappy() + { + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->once()) + ->method('getQuery') + ->with('code') + ->will($this->returnValue('99999000222220')); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'code' => '99999000222220', + 'state' => 'a393j2942789' + ])); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->never()) + ->method('error'); + + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with(__d('CakeDC/Users', 'Social account was associated.')); + + $fbToken = new AccessToken([ + 'access_token' => 'token', + 'tokenSecret' => null, + 'expires' => 1458423682 + ]); + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAccessToken', 'getResourceOwner']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->once()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo([ + 'code' => '99999000222220' + ]) + )->will($this->returnValue($fbToken)); + + $fbUser = new FacebookUser([ + 'id' => '9999911112255', + 'name' => 'Ful Name.', + 'username' => 'mock_username', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'Location' => 'mock_home', + 'bio' => 'mock_description', + 'link' => 'facebook-link-15579', + ]); + $ProviderMock->expects($this->once()) + ->method('getResourceOwner') + ->with( + $this->equalTo($fbToken) + )->will($this->returnValue($fbUser)); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' + ] + ]) + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->callbackLinkSocial('facebook'); + + $actual = $Table->SocialAccounts->find('all')->where(['reference' => '9999911112255'])->firstOrFail(); + + $expiresTime = new Time(); + $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); + + $expected = [ + 'provider' => 'Facebook', + 'username' => 'mock_username', + 'reference' => '9999911112255', + 'avatar' => 'https://graph.facebook.com/9999911112255/picture?type=large', + 'description' => 'mock_description', + 'token' => 'token', + 'token_secret' => null, + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'active' => true + ]; + foreach ($expected as $property => $value) { + $check = $actual->$property; + $this->assertEquals($value, $actual->$property); + } + $this->assertEquals($tokenExpires, $actual->token_expires->format('Y-m-d H:i:s')); + } + + /** + * test + * + * @return void + */ + public function testCallbackLinkSocialWithValidationErrors() + { + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + $user = TableRegistry::getTableLocator()->get('CakeDC/Users.Users')->get('00000000-0000-0000-0000-000000000001'); + $user->setErrors([ + 'social_accounts' => [ + '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') + ] + ]); + $Table = $this->getMockForModel('CakeDC/Users.Users', ['linkSocialAccount', 'get']); + $Table->setAlias('Users'); + + $Table->expects($this->once()) + ->method('get') + ->will($this->returnValue($user)); + + $Table->expects($this->once()) + ->method('linkSocialAccount') + ->will($this->returnValue($user)); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->once()) + ->method('getQuery') + ->with('code') + ->will($this->returnValue('99999000222220')); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'code' => '99999000222220', + 'state' => 'a393j2942789' + ])); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); + + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $fbToken = new AccessToken([ + 'access_token' => 'token', + 'tokenSecret' => null, + 'expires' => 1458423682 + ]); + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAccessToken', 'getResourceOwner']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->once()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo([ + 'code' => '99999000222220' + ]) + )->will($this->returnValue($fbToken)); + + $fbUser = new FacebookUser([ + 'id' => '9999911112255', + 'name' => 'Ful Name.', + 'username' => 'mock_username', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'Location' => 'mock_home', + 'bio' => 'mock_description', + 'link' => 'facebook-link-15579', + ]); + $ProviderMock->expects($this->once()) + ->method('getResourceOwner') + ->with( + $this->equalTo($fbToken) + )->will($this->returnValue($fbUser)); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' + ] + ]) + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->callbackLinkSocial('facebook'); + + $actual = $Table->SocialAccounts->exists(['reference' => '9999911112255']); + $this->assertFalse($actual); + } + + /** + * test + * + * @return void + */ + public function testCallbackLinkSocialFailGettingAccessToken() + { + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->once()) + ->method('getQuery') + ->with('code') + ->will($this->returnValue('99999000222220')); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'code' => '99999000222220', + 'state' => 'a393j2942789' + ])); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); + + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAccessToken', 'getResourceOwner']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->once()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo([ + 'code' => '99999000222220' + ]) + )->will($this->throwException(new \Exception)); + + $ProviderMock->expects($this->never()) + ->method('getResourceOwner'); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' + ] + ]) + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->callbackLinkSocial('facebook'); + + $actual = $Table->SocialAccounts->exists(['reference' => '9999911112255']); + $this->assertFalse($actual); + } + + /** + * test + * + * @return void + */ + public function testCallbackLinkSocialQueryHasErrors() + { + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->never()) + ->method('getQuery'); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'error' => 'We got some error', + 'code' => '99999000222220', + 'state' => 'a393j2942789' + ])); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with( + $this->equalTo(['action' => 'profile']) + ); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); + + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAccessToken', 'getResourceOwner']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->never()) + ->method('getAccessToken'); + + $ProviderMock->expects($this->never()) + ->method('getResourceOwner'); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' + ] + ]) + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->callbackLinkSocial('facebook'); + } + + /** + * test + * + * @return void + */ + public function testCallbackLinkSocialWrongState() + { + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->never()) + ->method('getQuery'); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'code' => '99999000222220', + 'state' => 'bd393j2942789' + ])); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with( + $this->equalTo(['action' => 'profile']) + ); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); + + $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') + ->setMethods(['getAccessToken', 'getResourceOwner']) + ->disableOriginalConstructor() + ->getMock(); + + $ProviderMock->expects($this->never()) + ->method('getAccessToken'); + + $ProviderMock->expects($this->never()) + ->method('getResourceOwner'); + + $this->Trait->expects($this->once()) + ->method('_createSocialProvider') + ->with( + $this->equalTo([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => 'testclientidtestclientid', + 'clientSecret' => 'testclientsecrettestclientsecret' + ] + ]) + ) + ->will($this->returnValue($ProviderMock)); + + $this->Trait->callbackLinkSocial('facebook'); + } + + /** + * test + * + * @return void + */ + public function testCallbackLinkSocialMissingCode() + { + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', 'getUsersTable', 'log']) + ->getMockForTrait(); + + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($Table)); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->_mockRequestGet(true); + $this->Trait->request->expects($this->never()) + ->method('getQuery'); + + $this->Trait->request->expects($this->once()) + ->method('getQueryParams') + ->will($this->returnValue([ + 'state' => 'bd393j2942789' + ])); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with( + $this->equalTo(['action' => 'profile']) + ); + + $this->_mockSession([ + 'SocialLink' => [ + 'oauth2state' => 'a393j2942789' + ] + ]); + $this->_mockAuthLoggedIn(); + $this->_mockDispatchEvent(new Event('event')); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->never()) + ->method('success'); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); + + $this->Trait->callbackLinkSocial('facebook'); + } +} diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php new file mode 100644 index 000000000..34f2094f2 --- /dev/null +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -0,0 +1,840 @@ +traitClassName = 'CakeDC\Users\Controller\Traits\LoginTrait'; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; + + parent::setUp(); + $request = new ServerRequest(); + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set']) + ->getMockForTrait(); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setConfig']) + ->disableOriginalConstructor() + ->getMock(); + + $this->Trait->request = $request; + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + } + + /** + * test + * + * @return void + */ + public function testLoginHappy() + { + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is']) + ->getMock(); + $this->Trait->request->expects($this->any()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $user = [ + 'id' => 1, + ]; + $redirectLoginOK = '/'; + $this->Trait->Auth->expects($this->at(0)) + ->method('identify') + ->will($this->returnValue($user)); + $this->Trait->Auth->expects($this->at(1)) + ->method('setUser') + ->with($user); + $this->Trait->Auth->expects($this->at(2)) + ->method('redirectUrl') + ->will($this->returnValue($redirectLoginOK)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with($redirectLoginOK); + $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) + ->disableOriginalConstructor() + ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) + ->getMock(); + $this->Trait->login(); + } + + /** + * test + * + * @return void + */ + public function testAfterIdentifyEmptyUser() + { + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is']) + ->getMock(); + $this->Trait->request->expects($this->any()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $user = []; + $this->Trait->Auth->expects($this->once()) + ->method('identify') + ->will($this->returnValue($user)); + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['error']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Username or password is incorrect', 'default', [], 'auth'); + $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) + ->disableOriginalConstructor() + ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) + ->getMock(); + $this->Trait->login(); + } + + /** + * test + * + * @return void + */ + public function testAfterIdentifyEmptyUserSocialLogin() + { + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') + ->setMethods(['dispatchEvent', 'redirect', '_isSocialLogin']) + ->getMockForTrait(); + $this->Trait->expects($this->any()) + ->method('_isSocialLogin') + ->will($this->returnValue(true)); + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is']) + ->getMock(); + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + + $this->Trait->login(); + } + + /** + * test + * + * @return void + */ + public function testLoginBeforeLoginReturningArray() + { + $user = [ + 'id' => 1 + ]; + $event = new Event('event'); + $event->result = $user; + $this->Trait->expects($this->at(0)) + ->method('dispatchEvent') + ->with(UsersAuthComponent::EVENT_BEFORE_LOGIN) + ->will($this->returnValue($event)); + $this->Trait->expects($this->at(1)) + ->method('dispatchEvent') + ->with(UsersAuthComponent::EVENT_AFTER_LOGIN) + ->will($this->returnValue(new Event('name'))); + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + $redirectLoginOK = '/'; + $this->Trait->Auth->expects($this->once()) + ->method('setUser') + ->with($user); + $this->Trait->Auth->expects($this->once()) + ->method('redirectUrl') + ->will($this->returnValue($redirectLoginOK)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with($redirectLoginOK); + $this->Trait->login(); + } + + /** + * test + * + * @return void + */ + public function testLoginBeforeLoginReturningStoppedEvent() + { + $event = new Event('event'); + $event->result = '/'; + $event->stopPropagation(); + $this->Trait->expects($this->at(0)) + ->method('dispatchEvent') + ->with(UsersAuthComponent::EVENT_BEFORE_LOGIN) + ->will($this->returnValue($event)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with('/'); + $this->Trait->login(); + } + + /** + * test + * + * @return void + */ + public function testLoginGet() + { + $this->_mockDispatchEvent(new Event('event')); + $socialLogin = Configure::read('Users.Social.login'); + Configure::write('Users.Social.login', false); + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->request->expects($this->at(0)) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + $this->Trait->request->expects($this->at(1)) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + $this->Trait->login(); + Configure::write('Users.Social.login', $socialLogin); + } + + /** + * test + * + * @return void + */ + public function testLogout() + { + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['logout', 'user']) + ->disableOriginalConstructor() + ->getMock(); + $redirectLogoutOK = '/'; + $this->Trait->Auth->expects($this->once()) + ->method('logout') + ->will($this->returnValue($redirectLogoutOK)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with($redirectLogoutOK); + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['success']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('You\'ve successfully logged out'); + $this->Trait->logout(); + } + + /** + * test + * + * @return void + */ + public function testFailedSocialLoginMissingEmail() + { + $event = new Entity(); + $event->data = [ + 'exception' => new MissingEmailException('Email not present'), + 'rawData' => [ + 'id' => 11111, + 'username' => 'user-1' + ] + ]; + $this->_mockFlash(); + $this->_mockRequestGet(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please enter your email'); + + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); + + $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); + } + + /** + * test + * + * @return void + */ + public function testFailedSocialUserNotActive() + { + $event = new Entity(); + $event->data = [ + 'exception' => new UserNotActiveException('Facebook user-1'), + 'rawData' => [ + 'id' => 111111, + 'username' => 'user-1' + ] + ]; + $this->_mockFlash(); + $this->_mockRequestGet(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Your user has not been validated yet. Please check your inbox for instructions'); + + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + + $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); + } + + /** + * test + * + * @return void + */ + public function testFailedSocialUserAccountNotActive() + { + $event = new Entity(); + $event->data = [ + 'exception' => new AccountNotActiveException('Facebook user-1'), + 'rawData' => [ + 'id' => 111111, + 'username' => 'user-1' + ] + ]; + $this->_mockFlash(); + $this->_mockRequestGet(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Your social account has not been validated yet. Please check your inbox for instructions'); + + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + + $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); + } + + /** + * test + * + * @return void + */ + public function testFailedSocialUserAccount() + { + $event = new Entity(); + $event->data = [ + 'rawData' => [ + 'id' => 111111, + 'username' => 'user-1' + ] + ]; + $this->_mockFlash(); + $this->_mockRequestGet(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Issues trying to log in with your social account'); + + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + + $this->Trait->failedSocialLogin(null, $event->data['rawData'], true); + } + + /** + * testVerifyHappy + * + */ + public function testVerifyHappy() + { + Configure::write('Users.GoogleAuthenticator.login', true); + + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is', 'getData', 'allow', 'getSession']) + ->getMock(); + $this->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + + $this->_mockSession([ + 'temporarySession' => [ + 'id' => 1, + 'secret_verified' => 1, + ] + ]); + $this->Trait->verify(); + } + /** + * testVerifyGoogleAuthenticator + * + */ + public function testVerifyGoogleAuthenticator() + { + Configure::write('Users.GoogleAuthenticator.login', true); + + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is', 'getData', 'allow', 'getSession']) + ->getMock(); + $this->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + + $this->_mockSession([ + 'temporarySession' => [ + 'id' => 1, + 'secret_verified' => 1, + ], + 'Users' => [ + 'hasRememberMe' => 1 + ] + ]); + $this->Trait->verify(); + } + + /** + * testVerifyNoUser + * + */ + public function testVerifyNoUser() + { + Configure::write('Users.GoogleAuthenticator.login', true); + + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is', 'getData', 'allow', 'getSession']) + ->getMock(); + $this->Trait->request->expects($this->never()) + ->method('is') + ->with('post'); + $this->_mockSession([]); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Invalid request.'); + $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) + ->disableOriginalConstructor() + ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) + ->getMock(); + $this->Trait->verify(); + } + + /** + * testVerifyHappy + * + */ + public function testVerifyNotEnabled() + { + $this->_mockFlash(); + Configure::write('Users.GoogleAuthenticator.login', false); + $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) + ->disableOriginalConstructor() + ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) + ->getMock(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Please enable Google Authenticator first.'); + $this->Trait->verify(); + } + + /** + * testVerifyHappy + * + */ + public function testVerifyGetShowQR() + { + Configure::write('Users.GoogleAuthenticator.login', true); + + $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) + ->disableOriginalConstructor() + ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) + ->getMock(); + + $this->Trait->request = $this->getMockBuilder(ServerRequest::class) + ->setMethods(['is', 'getData', 'allow', 'getSession']) + ->getMock(); + $this->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + $this->_mockSession([ + 'temporarySession' => [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'email' => 'email@example.com', + 'secret_verified' => 0, + ] + ]); + $this->Trait->GoogleAuthenticator->expects($this->at(0)) + ->method('createSecret') + ->will($this->returnValue('newSecret')); + $this->Trait->GoogleAuthenticator->expects($this->at(1)) + ->method('getQRCodeImageAsDataUri') + ->with('email@example.com', 'newSecret') + ->will($this->returnValue('newDataUriGenerated')); + $this->Trait->expects($this->at(0)) + ->method('set') + ->with(['secretDataUri' => 'newDataUriGenerated']); + $this->Trait->verify(); + } + + /** + * Tests that a GET request causes a a new secret to be generated in case it's + * not already present in the session. + */ + public function testVerifyGetGeneratesNewSecret() + { + Configure::write('Users.GoogleAuthenticator.login', true); + + $this->Trait->GoogleAuthenticator = $this + ->getMockBuilder(GoogleAuthenticatorComponent::class) + ->disableOriginalConstructor() + ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) + ->getMock(); + + $this->Trait->request = $this + ->getMockBuilder(ServerRequest::class) + ->setMethods(['is', 'getData', 'allow', 'getSession']) + ->getMock(); + $this->Trait->request + ->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + + $this->Trait->GoogleAuthenticator + ->expects($this->at(0)) + ->method('createSecret') + ->will($this->returnValue('newSecret')); + $this->Trait->GoogleAuthenticator + ->expects($this->at(1)) + ->method('getQRCodeImageAsDataUri') + ->with('email@example.com', 'newSecret') + ->will($this->returnValue('newDataUriGenerated')); + + $session = $this->_mockSession([ + 'temporarySession' => [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'email' => 'email@example.com', + 'secret_verified' => false, + ] + ]); + $this->Trait->verify(); + + $this->assertEquals( + [ + 'temporarySession' => [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'email' => 'email@example.com', + 'secret_verified' => false, + 'secret' => 'newSecret' + ] + ], + $session->read() + ); + } + + /** + * Tests that a GET request does not cause a new secret to be generated in case + * it's already present in the session. + */ + public function testVerifyGetDoesNotGenerateNewSecret() + { + Configure::write('Users.GoogleAuthenticator.login', true); + + $this->Trait->GoogleAuthenticator = $this + ->getMockBuilder(GoogleAuthenticatorComponent::class) + ->disableOriginalConstructor() + ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) + ->getMock(); + + $this->Trait->request = $this + ->getMockBuilder(ServerRequest::class) + ->setMethods(['is', 'getData', 'allow', 'getSession']) + ->getMock(); + $this->Trait->request + ->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + + $this->Trait->GoogleAuthenticator + ->expects($this->never()) + ->method('createSecret'); + $this->Trait->GoogleAuthenticator + ->expects($this->at(0)) + ->method('getQRCodeImageAsDataUri') + ->with('email@example.com', 'alreadyPresentSecret') + ->will($this->returnValue('newDataUriGenerated')); + + $session = $this->_mockSession([ + 'temporarySession' => [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'email' => 'email@example.com', + 'secret_verified' => false, + 'secret' => 'alreadyPresentSecret' + ] + ]); + $this->Trait->verify(); + + $this->assertEquals( + [ + 'temporarySession' => [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'email' => 'email@example.com', + 'secret_verified' => false, + 'secret' => 'alreadyPresentSecret' + ] + ], + $session->read() + ); + } + + /** + * Tests that posting a valid code causes verification to succeed. + */ + public function testVerifyPostValidCode() + { + Configure::write('Users.GoogleAuthenticator.login', true); + + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) + ->disableOriginalConstructor() + ->setMethods(['createSecret', 'verifyCode', 'getQRCodeImageAsDataUri']) + ->getMock(); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setUser', 'redirectUrl']) + ->disableOriginalConstructor() + ->getMock(); + + $this->Trait->request = $this->getMockBuilder(ServerRequest::class) + ->setMethods(['is', 'getData', 'allow', 'getSession']) + ->getMock(); + $this->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->with('code') + ->will($this->returnValue('123456')); + + $this->Trait->GoogleAuthenticator + ->expects($this->never()) + ->method('createSecret'); + $this->Trait->GoogleAuthenticator + ->expects($this->at(0)) + ->method('getQRCodeImageAsDataUri') + ->with('email@example.com', 'yyy') + ->will($this->returnValue('newDataUriGenerated')); + $this->Trait->GoogleAuthenticator + ->expects($this->at(1)) + ->method('verifyCode') + ->with('yyy', '123456') + ->will($this->returnValue(true)); + + $this->Trait->Auth + ->expects($this->at(0)) + ->method('setUser') + ->with([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'email' => 'email@example.com', + 'secret_verified' => true + ]); + $this->Trait->Auth + ->expects($this->at(1)) + ->method('redirectUrl') + ->will($this->returnValue('/')); + + $this->assertFalse($this->table->exists([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'secret_verified' => true + ])); + + $session = $this->_mockSession([ + 'temporarySession' => [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'email' => 'email@example.com', + 'secret_verified' => false, + 'secret' => 'yyy' + ] + ]); + $this->Trait->verify(); + + $this->assertTrue($this->table->exists([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'secret_verified' => true + ])); + + $this->assertEmpty($session->read()); + } + + /** + * Tests that posting and invalid code causes verification to fail. + */ + public function testVerifyPostInvalidCode() + { + Configure::write('Users.GoogleAuthenticator.login', true); + + $this->Trait->GoogleAuthenticator = $this + ->getMockBuilder(GoogleAuthenticatorComponent::class) + ->disableOriginalConstructor() + ->setMethods(['createSecret', 'verifyCode', 'getQRCodeImageAsDataUri']) + ->getMock(); + + $this->Trait->Auth = $this + ->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['setUser']) + ->disableOriginalConstructor() + ->getMock(); + + $this->Trait->Flash = $this + ->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['error']) + ->disableOriginalConstructor() + ->getMock(); + + $this->Trait->request = $this + ->getMockBuilder(ServerRequest::class) + ->setMethods(['is', 'getData', 'allow', 'getSession']) + ->getMock(); + $this->Trait->request + ->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + $this->Trait->request + ->expects($this->once()) + ->method('getData') + ->with('code') + ->will($this->returnValue('invalid')); + + $this->Trait->GoogleAuthenticator + ->expects($this->never()) + ->method('createSecret'); + $this->Trait->GoogleAuthenticator + ->expects($this->at(0)) + ->method('getQRCodeImageAsDataUri') + ->with('email@example.com', 'yyy') + ->will($this->returnValue('newDataUriGenerated')); + $this->Trait->GoogleAuthenticator + ->expects($this->at(1)) + ->method('verifyCode') + ->with('yyy', 'invalid') + ->will($this->returnValue(false)); + + $this->Trait->Auth + ->expects($this->never()) + ->method('setUser'); + + $this->Trait->Flash + ->expects($this->once()) + ->method('error') + ->with('Verification code is invalid. Try again', 'default', [], 'auth'); + + $this->Trait + ->expects($this->once()) + ->method('redirect') + ->with([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + 'prefix' => false, + '?' => [] + ]); + + $this->assertFalse($this->table->exists([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'secret_verified' => true + ])); + + $session = $this->_mockSession([ + 'temporarySession' => [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'email' => 'email@example.com', + 'secret_verified' => false, + 'secret' => 'yyy' + ] + ]); + $this->Trait->verify(); + + $this->assertFalse($this->table->exists([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'secret_verified' => true + ])); + + $this->assertEmpty($session->read()); + } + + /** + * Mock session and mock session attributes + * + * @return \Cake\Http\Session + */ + protected function _mockSession($attributes) + { + $session = new \Cake\Http\Session(); + + foreach ($attributes as $field => $value) { + $session->write($field, $value); + } + + $this->Trait->request + ->expects($this->any()) + ->method('getSession') + ->willReturn($session); + + return $session; + } +} diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php new file mode 100644 index 000000000..f4d292765 --- /dev/null +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -0,0 +1,470 @@ +traitClassName = 'CakeDC\Users\Controller\Traits\PasswordManagementTrait'; + $this->traitMockMethods = ['set', 'redirect', 'validate', 'log', 'dispatchEvent']; + $this->mockDefaultEmail = true; + parent::setUp(); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordHappy() + { + $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue([ + 'password' => 'new', + 'password_confirm' => 'new', + ])); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); + $this->Trait->Flash->expects($this->any()) + ->method('success') + ->with('Password has been changed successfully'); + $this->Trait->changePassword(); + $hasher = PasswordHasherFactory::build('Default'); + $this->assertTrue($hasher->check('new', $this->table->get('00000000-0000-0000-0000-000000000001')->password)); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordWithError() + { + $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue([ + 'password' => 'new', + 'password_confirm' => 'wrong_new', + ])); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Password could not be changed'); + $this->Trait->changePassword(); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordWithAfterChangeEvent() + { + $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue([ + 'password' => 'new', + 'password_confirm' => 'new', + ])); + $event = new Event('event'); + $event->result = [ + 'action' => 'newAction', + ]; + $this->Trait->expects($this->once()) + ->method('dispatchEvent') + ->will($this->returnValue($event)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'newAction']); + $this->Trait->Flash->expects($this->any()) + ->method('success') + ->with('Password has been changed successfully'); + $this->Trait->changePassword(); + $hasher = PasswordHasherFactory::build('Default'); + $this->assertTrue($hasher->check('new', $this->table->get('00000000-0000-0000-0000-000000000001')->password)); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordWithSamePassword() + { + $this->assertEquals( + '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', + $this->table->get('00000000-0000-0000-0000-000000000006')->password + ); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue([ + 'current_password' => '12345', + 'password' => '12345', + 'password_confirm' => '12345', + ])); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('You cannot use the current password as the new one'); + $this->Trait->changePassword(); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordWithEmptyCurrentPassword() + { + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue([ + 'current_password' => '', + 'password' => '54321', + 'password_confirm' => '54321', + ])); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Password could not be changed'); + $this->Trait->changePassword(); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordWithWrongCurrentPassword() + { + $this->assertEquals( + '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', + $this->table->get('00000000-0000-0000-0000-000000000006')->password + ); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue([ + 'current_password' => 'wrong-password', + 'password' => '12345', + 'password_confirm' => '12345', + ])); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The current password does not match'); + $this->Trait->changePassword(); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordWithInvalidUser() + { + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => '12312312-0000-0000-0000-000000000002', 'password' => 'invalid-pass']); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue([ + 'password' => 'new', + 'password_confirm' => 'new', + ])); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('User was not found'); + $this->Trait->changePassword(); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordGetLoggedIn() + { + $this->_mockRequestGet(); + $this->_mockAuthLoggedIn(); + $this->Trait->expects($this->any()) + ->method('set') + ->will($this->returnCallback(function ($param1, $param2 = null) { + if ($param1 === 'validatePassword') { + TestCase::assertEquals($param2, true); + } + })); + $this->Trait->changePassword(); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordGetNotLoggedInInsideResetPasswordFlow() + { + $this->_mockRequestGet(true); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockSession([ + Configure::read('Users.Key.Session.resetPasswordUserId') => '00000000-0000-0000-0000-000000000001' + ]); + $this->Trait->expects($this->any()) + ->method('set') + ->will($this->returnCallback(function ($param1, $param2 = null) { + if ($param1 === 'validatePassword') { + TestCase::assertEquals($param2, false); + } + })); + $this->Trait->changePassword(); + } + + /** + * test + * + * @return void + */ + public function testChangePasswordGetNotLoggedInOutsideResetPasswordFlow() + { + $this->_mockRequestGet(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('User was not found'); + $this->Trait->changePassword(); + } + + /** + * test + * + * @return void + */ + public function testResetPassword() + { + $token = 'token'; + $this->Trait->expects($this->once()) + ->method('validate') + ->with('password', $token); + $this->Trait->resetPassword($token); + } + + /** + * test + * + * @return void + */ + public function testRequestResetPasswordGet() + { + $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get('00000000-0000-0000-0000-000000000001')->token); + $this->_mockRequestGet(); + $this->_mockFlash(); + $this->Trait->request->expects($this->never()) + ->method('getData'); + $this->Trait->requestResetPassword(); + } + + /** + * test + * + * @return void + */ + public function testRequestPasswordHappy() + { + $this->assertEquals('6614f65816754310a5f0553436dd89e9', $this->table->get('00000000-0000-0000-0000-000000000002')->token); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $reference = 'user-2'; + $this->Trait->request->expects($this->once()) + ->method('getData') + ->with('reference') + ->will($this->returnValue($reference)); + $this->Trait->Flash->expects($this->any()) + ->method('success') + ->with('Please check your email to continue with password reset process'); + $this->Trait->requestResetPassword(); + $this->assertNotEquals('xxx', $this->table->get('00000000-0000-0000-0000-000000000002')->token); + } + + /** + * test + * + * @return void + */ + public function testRequestPasswordInvalidUser() + { + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => 'invalid-id', 'password' => 'invalid-pass']); + $this->_mockFlash(); + $reference = '12312312-0000-0000-0000-000000000002'; + $this->Trait->request->expects($this->once()) + ->method('getData') + ->with('reference') + ->will($this->returnValue($reference)); + $this->Trait->Flash->expects($this->any()) + ->method('error') + ->with('User 12312312-0000-0000-0000-000000000002 was not found'); + $this->Trait->requestResetPassword(); + } + + /** + * test + * + * @return void + */ + public function testRequestPasswordEmptyReference() + { + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(['id' => 'invalid-id', 'password' => 'invalid-pass']); + $this->_mockFlash(); + $reference = ''; + $this->Trait->request->expects($this->once()) + ->method('getData') + ->with('reference') + ->will($this->returnValue($reference)); + $this->Trait->Flash->expects($this->any()) + ->method('error') + ->with('Token could not be reset'); + $this->Trait->requestResetPassword(); + } + + /** + * @dataProvider ensureUserActiveForResetPasswordFeature + * + * @return void + */ + public function testEnsureUserActiveForResetPasswordFeature($ensureActive) + { + $expectError = $this->never(); + + if ($ensureActive) { + Configure::write('Users.Registration.ensureActive', true); + $expectError = $this->once(); + } + + $this->assertEquals('ae93ddbe32664ce7927cf0c5c5a5e59d', $this->table->get('00000000-0000-0000-0000-000000000001')->token); + $this->_mockRequestPost(); + $this->_mockFlash(); + $reference = 'user-1'; + $this->Trait->request->expects($this->once()) + ->method('getData') + ->with('reference') + ->will($this->returnValue($reference)); + $this->Trait->Flash->expects($expectError) + ->method('error') + ->with('The user is not active'); + $this->Trait->requestResetPassword(); + $this->assertNotEquals('xxx', $this->table->get('00000000-0000-0000-0000-000000000001')->token); + } + + public function ensureUserActiveForResetPasswordFeature() + { + $ensureActive = true; + $defaultBehavior = false; + + return [ + [$ensureActive], + [$defaultBehavior] + ]; + } + + /** + * @dataProvider ensureGoogleAuthenticatorResets + * + * @return void + */ + public function testRequestGoogleAuthTokenResetWithValidUser($userId, $entityId, $method, $msg) + { + $this->_mockRequestPost(); + $this->_mockFlash(); + + $user = $this->table->get($userId); + + $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['user', 'config']) + ->disableOriginalConstructor() + ->getMock(); + + $this->Trait->Auth->expects($this->any()) + ->method('user') + ->will($this->returnValue($user)); + + $this->Trait->Flash->expects($this->any()) + ->method($method) + ->with($msg); + + $this->Trait->resetGoogleAuthenticator($entityId); + } + + public function ensureGoogleAuthenticatorResets() + { + $error = 'error'; + $success = 'success'; + $errorMsg = 'You are not allowed to reset users Google Authenticator token'; + $successMsg = 'Google Authenticator token was successfully reset'; + + return [ + //is_superuser = true. + ['00000000-0000-0000-0000-000000000003', null, $success, $successMsg], + //is_superuser = true. + ['00000000-0000-0000-0000-000000000001', null, $success, $successMsg], + //is_superuser = false, and not his profile. + ['00000000-0000-0000-0000-000000000004', '00000000-0000-0000-0000-000000000001', $error, $errorMsg], + //is_superuser = false, editing own record. + ['00000000-0000-0000-0000-000000000004', '00000000-0000-0000-0000-000000000004', $success, $successMsg], + //is_superuser = false, and no entity-id given. + ['00000000-0000-0000-0000-000000000004', null, $error, $errorMsg], + ]; + } +} diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php new file mode 100644 index 000000000..f0ab42c68 --- /dev/null +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -0,0 +1,113 @@ +traitClassName = 'CakeDC\Users\Controller\Traits\ProfileTrait'; + $this->traitMockMethods = ['set', 'getUsersTable', 'redirect', 'validate']; + parent::setUp(); + } + + /** + * test + * + * @return void + */ + public function testProfileGetNotLoggedInUserNotFound() + { + $userId = '00000000-0000-0000-0000-000000000000'; //not found + $this->_mockRequestGet(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('User was not found'); + $this->Trait->profile($userId); + } + + /** + * test + * + * @return void + */ + public function testProfileGetLoggedInUserNotFound() + { + $userId = '00000000-0000-0000-0000-000000000000'; //not found + $this->_mockRequestGet(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('User was not found'); + $this->Trait->profile($userId); + } + + /** + * test + * + * @return void + */ + public function testProfileGetNotLoggedInEmptyId() + { + $this->_mockRequestGet(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Not authorized, please login first'); + $this->Trait->profile(); + } + + /** + * test + * + * @return void + */ + public function testProfileGetLoggedInMyProfile() + { + $this->_mockRequestGet(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->Trait->expects($this->any()) + ->method('set') + ->will($this->returnCallback(function ($param1, $param2 = null) { + if ($param1 === 'avatarPlaceholder') { + BaseTraitTest::assertEquals('CakeDC/Users.avatar_placeholder.png', $param2); + } elseif (is_array($param1)) { + BaseTraitTest::assertEquals('user-1', $param1['user']->username); + } + })); + $this->Trait->profile(); + } +} diff --git a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php new file mode 100644 index 000000000..a72250221 --- /dev/null +++ b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php @@ -0,0 +1,123 @@ +Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait') + ->setMethods(['_getReCaptchaInstance']) + ->getMockForTrait(); + } + + /** + * tearDown callback + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + } + + /** + * testValidateValidReCaptcha + * + * @return void + */ + public function testValidateValidReCaptcha() + { + $ReCaptcha = $this->getMockBuilder('ReCaptcha\ReCaptcha') + ->setMethods(['verify']) + ->disableOriginalConstructor() + ->getMock(); + $Response = $this->getMockBuilder('ReCaptcha\Response') + ->setMethods(['isSuccess']) + ->disableOriginalConstructor() + ->getMock(); + $Response->expects($this->any()) + ->method('isSuccess') + ->will($this->returnValue(true)); + $ReCaptcha->expects($this->any()) + ->method('verify') + ->with('value') + ->will($this->returnValue($Response)); + $this->Trait->expects($this->any()) + ->method('_getReCaptchaInstance') + ->will($this->returnValue($ReCaptcha)); + $this->Trait->validateReCaptcha('value', '255.255.255.255'); + } + + /** + * testValidateInvalidReCaptcha + * + * @return void + */ + public function testValidateInvalidReCaptcha() + { + $ReCaptcha = $this->getMockBuilder('ReCaptcha\ReCaptcha') + ->setMethods(['verify']) + ->disableOriginalConstructor() + ->getMock(); + $Response = $this->getMockBuilder('ReCaptcha\Response') + ->setMethods(['isSuccess']) + ->disableOriginalConstructor() + ->getMock(); + $Response->expects($this->any()) + ->method('isSuccess') + ->will($this->returnValue(false)); + $ReCaptcha->expects($this->any()) + ->method('verify') + ->with('invalid') + ->will($this->returnValue($Response)); + $this->Trait->expects($this->any()) + ->method('_getReCaptchaInstance') + ->will($this->returnValue($ReCaptcha)); + $this->Trait->validateReCaptcha('invalid', '255.255.255.255'); + } + + public function testGetRecaptchaInstance() + { + Configure::write('Users.reCaptcha.secret', 'secret'); + $trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait')->getMockForTrait(); + $method = new ReflectionMethod(get_class($trait), '_getReCaptchaInstance'); + $method->setAccessible(true); + $method->invokeArgs($trait, []); + $this->assertNotEmpty($method->invoke($trait)); + } + + public function testGetRecaptchaInstanceNull() + { + $trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait')->getMockForTrait(); + $method = new ReflectionMethod(get_class($trait), '_getReCaptchaInstance'); + $method->setAccessible(true); + $method->invokeArgs($trait, []); + $this->assertNull($method->invoke($trait)); + } + + public function testValidateReCaptchaFalse() + { + $trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait')->getMockForTrait(); + $this->assertFalse($this->Trait->validateReCaptcha('value', '255.255.255.255')); + } +} diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php new file mode 100644 index 000000000..6050b9bda --- /dev/null +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -0,0 +1,399 @@ +traitClassName = 'CakeDC\Users\Controller\Traits\RegisterTrait'; + $this->traitMockMethods = ['validate', 'dispatchEvent', 'set', 'validateReCaptcha', 'redirect']; + $this->mockDefaultEmail = true; + parent::setUp(); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + } + + /** + * test + * + * @return void + */ + public function testValidateEmail() + { + $token = 'token'; + $this->Trait->expects($this->once()) + ->method('validate') + ->with('email', $token); + $this->Trait->validateEmail($token); + } + + /** + * test + * + * @return void + */ + public function testRegister() + { + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please validate your account before log in'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ])); + + $this->Trait->register(); + + $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * Triggering beforeRegister event and not able to register the user + * + * @return void + */ + public function testRegisterWithEventFalseResult() + { + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(new Event('Users.Component.UsersAuth.beforeRegister'), ['username' => 'hello']); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The user could not be saved'); + $this->Trait->expects($this->never()) + ->method('redirect'); + $this->Trait->request->expects($this->never()) + ->method('is'); + + $this->Trait->register(); + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * Triggering beforeRegister event and registering the user successfully + * + * @return void + */ + public function testRegisterWithEventSuccessResult() + { + $data = [ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ]; + + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(new Event('Users.Component.UsersAuth.beforeRegister'), $data); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->will($this->returnValue($data)); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please validate your account before log in'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->expects($this->never()) + ->method('is'); + + $this->Trait->register(); + $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + */ + public function testRegisterReCaptcha() + { + Configure::write('Users.reCaptcha.registration', true); + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please validate your account before log in'); + $this->Trait->expects($this->once()) + ->method('validateRecaptcha') + ->will($this->returnValue(true)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->expects($this->at(0)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ])); + + $this->Trait->register(); + + $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + */ + public function testRegisterValidationErrors() + { + Configure::write('Users.reCaptcha.registration', true); + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The user could not be saved'); + $this->Trait->expects($this->once()) + ->method('validateRecaptcha') + ->will($this->returnValue(true)); + $this->Trait->expects($this->never()) + ->method('redirect'); + $this->Trait->request->expects($this->at(0)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'not-matching', + 'tos' => 1 + ])); + + $this->Trait->register(); + + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + */ + public function testRegisterRecaptchaNotValid() + { + Configure::write('Users.reCaptcha.registration', true); + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Invalid reCaptcha'); + $this->Trait->expects($this->once()) + ->method('validateRecaptcha') + ->will($this->returnValue(false)); + $this->Trait->request->expects($this->at(0)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ])); + + $this->Trait->register(); + + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + */ + public function testRegisterGet() + { + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestGet(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->never()) + ->method('success'); + $this->Trait->expects($this->never()) + ->method('validateRecaptcha'); + $this->Trait->expects($this->never()) + ->method('redirect'); + $this->Trait->register(); + + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + */ + public function testRegisterRecaptchaDisabled() + { + Configure::write('Users.Registration.reCaptcha', false); + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please validate your account before log in'); + $this->Trait->expects($this->never()) + ->method('validateRecaptcha'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->expects($this->at(0)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ])); + + $this->Trait->register(); + + $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + * @expectedException Cake\Http\Exception\NotFoundException + */ + public function testRegisterNotEnabled() + { + Configure::write('Users.Registration.active', false); + $this->_mockRequestPost(); + $this->_mockAuth(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->register(); + } + + /** + * test + * + * @return void + */ + public function testRegisterLoggedInUserAllowed() + { + Configure::write('Users.Registration.allowLoggedIn', true); + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Please validate your account before log in'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->request->expects($this->at(0)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testRegistration', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1 + ])); + + $this->Trait->register(); + + $this->assertEquals(1, $this->table->find()->where(['username' => 'testRegistration'])->count()); + } + + /** + * test + * + * @return void + */ + public function testRegisterLoggedInUserNotAllowed() + { + Configure::write('Users.Registration.allowLoggedIn', false); + $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); + $this->_mockRequestPost(); + $this->_mockAuthLoggedIn(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('You must log out to register a new user account'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(Configure::read('Users.Profile.route')); + $this->Trait->request->expects($this->never()) + ->method('getData') + ->with(); + + $this->Trait->register(); + } +} diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php new file mode 100644 index 000000000..be5358db3 --- /dev/null +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -0,0 +1,306 @@ +traitClassName = 'CakeDC\Users\Controller\Traits\SimpleCrudTrait'; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set', 'loadModel', 'paginate']; + parent::setUp(); + $viewVarsContainer = $this; + $this->Trait->expects($this->any()) + ->method('set') + ->will($this->returnCallback(function ($param1, $param2 = null) use ($viewVarsContainer) { + $viewVarsContainer->viewVars[$param1] = $param2; + })); + $this->Trait->expects($this->once()) + ->method('loadModel') + ->will($this->returnValue($this->table)); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + $this->viewVars = null; + parent::tearDown(); + } + + /** + * test + * + * @return void + */ + public function testIndex() + { + $this->Trait->expects($this->once()) + ->method('paginate') + ->with($this->table) + ->will($this->returnValue([])); + $this->Trait->index(); + $expected = [ + 'Users' => [], + 'tableAlias' => 'Users', + '_serialize' => [ + 'Users', + 'tableAlias' + ] + ]; + $this->assertSame($expected, $this->viewVars); + } + + /** + * test + * + * @return void + */ + public function testView() + { + $id = '00000000-0000-0000-0000-000000000001'; + $this->Trait->view($id); + $expected = [ + 'Users' => $this->table->get($id), + 'tableAlias' => 'Users', + '_serialize' => [ + 'Users', + 'tableAlias' + ] + ]; + $this->assertEquals($expected, $this->viewVars); + } + + /** + * test + * + * @return void + * @expectedException Cake\Datasource\Exception\RecordNotFoundException + */ + public function testViewNotFound() + { + $this->Trait->view('00000000-0000-0000-0000-000000000000'); + } + + /** + * test + * + * @return void + * @expectedException Cake\Datasource\Exception\InvalidPrimaryKeyException + */ + public function testViewInvalidPK() + { + $this->Trait->view(); + } + + /** + * test + * + * @return void + */ + public function testAddGet() + { + $this->_mockRequestGet(); + $this->Trait->add(); + $expected = [ + 'Users' => $this->table->newEntity(), + 'tableAlias' => 'Users', + '_serialize' => [ + 'Users', + 'tableAlias' + ] + ]; + $this->assertEquals($expected, $this->viewVars); + } + + /** + * test + * + * @return void + */ + public function testAddPostHappy() + { + $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); + $this->_mockRequestPost(); + $this->_mockFlash(); + $this->Trait->request->expects($this->at(0)) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + $this->Trait->request->expects($this->at(1)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + ])); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('The User has been saved'); + + $this->Trait->add(); + + $this->assertSame(1, $this->table->find()->where(['username' => 'testuser'])->count()); + } + + /** + * test + * + * @return void + */ + public function testAddPostErrors() + { + $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); + $this->_mockRequestPost(); + $this->_mockFlash(); + $this->Trait->request->expects($this->at(0)) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + $this->Trait->request->expects($this->at(1)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'first_name' => 'test', + 'last_name' => 'user', + ])); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The User could not be saved'); + + $this->Trait->add(); + + $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); + } + + /** + * test + * + * @return void + */ + public function testEditPostHappy() + { + $this->assertEquals('user-1@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); + $this->_mockRequestPost(['patch', 'post', 'put']); + $this->_mockFlash(); + $this->Trait->request->expects($this->at(0)) + ->method('is') + ->with(['patch', 'post', 'put']) + ->will($this->returnValue(true)); + $this->Trait->request->expects($this->at(1)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'email' => 'newtestuser@test.com', + ])); + + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('The User has been saved'); + + $this->Trait->edit('00000000-0000-0000-0000-000000000001'); + + $this->assertEquals('newtestuser@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); + } + + /** + * test + * + * @return void + */ + public function testEditPostErrors() + { + $this->assertEquals('user-1@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); + $this->_mockRequestPost(['patch', 'post', 'put']); + $this->_mockFlash(); + $this->Trait->request->expects($this->at(0)) + ->method('is') + ->with(['patch', 'post', 'put']) + ->will($this->returnValue(true)); + $this->Trait->request->expects($this->at(1)) + ->method('getData') + ->with() + ->will($this->returnValue([ + 'email' => 'not-an-email', + ])); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The User could not be saved'); + + $this->Trait->edit('00000000-0000-0000-0000-000000000001'); + + $this->assertEquals('user-1@test.com', $this->table->get('00000000-0000-0000-0000-000000000001')->email); + } + + /** + * test + * + * @return void + * @expectedException Cake\Datasource\Exception\RecordNotFoundException + */ + public function testDeleteHappy() + { + $this->assertNotEmpty($this->table->get('00000000-0000-0000-0000-000000000001')); + $this->_mockRequestPost(); + $this->Trait->request->expects($this->any()) + ->method('allow') + ->with(['post', 'delete']) + ->will($this->returnValue(true)); + + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('The User has been deleted'); + + $this->Trait->delete('00000000-0000-0000-0000-000000000001'); + + $this->table->get('00000000-0000-0000-0000-000000000001'); + } + + /** + * test + * + * @return void + * @expectedException Cake\Datasource\Exception\RecordNotFoundException + */ + public function testDeleteNotFound() + { + $this->assertNotEmpty($this->table->get('00000000-0000-0000-0000-000000000001')); + $this->_mockRequestPost(); + $this->Trait->request->expects($this->any()) + ->method('allow') + ->with(['post', 'delete']) + ->will($this->returnValue(true)); + + $this->Trait->delete('00000000-0000-0000-0000-000000000000'); + } +} diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php new file mode 100644 index 000000000..054bc7cb1 --- /dev/null +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -0,0 +1,180 @@ +controller = $this->getMockBuilder('Cake\Controller\Controller') + ->setMethods(['header', 'redirect', 'render', '_stop']) + ->getMock(); + + $this->controller->Trait = $this->getMockForTrait( + 'CakeDC\Users\Controller\Traits\SocialTrait', + [], + '', + true, + true, + true, + ['_getOpauthInstance', 'redirect', '_generateOpauthCompleteUrl', '_afterIdentifyUser', '_validateRegisterPost'] + ); + } + + public function tearDown() + { + parent::tearDown(); + } + + /** + * Test socialEmail + * + */ + public function testSocialEmail() + { + $session = $this->getMockBuilder('Cake\Http\Session') + ->setMethods(['check', 'delete']) + ->getMock(); + $session->expects($this->at(0)) + ->method('check') + ->with('Users.social') + ->will($this->returnValue('social_key')); + + $session->expects($this->at(1)) + ->method('delete') + ->with('Flash.auth'); + + $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['getSession']) + ->getMock(); + $this->controller->Trait->request->expects($this->any()) + ->method('getSession') + ->will($this->returnValue($session)); + + $this->controller->Trait->socialEmail(); + } + + /** + * Test socialEmail + * + * @expectedException \Cake\Http\Exception\NotFoundException + */ + public function testSocialEmailInvalid() + { + $session = $this->getMockBuilder('Cake\Http\Session') + ->setMethods(['check']) + ->getMock(); + $session->expects($this->once()) + ->method('check') + ->with('Users.social') + ->will($this->returnValue(null)); + + $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['getSession']) + ->getMock(); + $this->controller->Trait->request->expects($this->once()) + ->method('getSession') + ->will($this->returnValue($session)); + + $this->controller->Trait->socialEmail(); + } + + public function testSocialEmailPostValidateFalse() + { + $session = $this->getMockBuilder('Cake\Http\Session') + ->setMethods(['check', 'delete']) + ->getMock(); + $session->expects($this->any()) + ->method('check') + ->with('Users.social') + ->will($this->returnValue(true)); + + $session->expects($this->once()) + ->method('delete') + ->with('Flash.auth'); + + $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['getSession', 'is']) + ->getMock(); + $this->controller->Trait->request->expects($this->any()) + ->method('getSession') + ->will($this->returnValue($session)); + + $this->controller->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + + $this->controller->Trait->expects($this->once()) + ->method('_validateRegisterPost') + ->will($this->returnValue(false)); + + $this->controller->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['error']) + ->disableOriginalConstructor() + ->getMock(); + + $this->controller->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The reCaptcha could not be validated'); + + $this->controller->Trait->socialEmail(); + } + + public function testSocialEmailPostValidateTrue() + { + $session = $this->getMockBuilder('Cake\Http\Session') + ->setMethods(['check', 'delete']) + ->getMock(); + $session->expects($this->any()) + ->method('check') + ->with('Users.social') + ->will($this->returnValue(true)); + + $session->expects($this->once()) + ->method('delete') + ->with('Flash.auth'); + + $this->controller->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['getSession', 'is']) + ->getMock(); + $this->controller->Trait->request->expects($this->any()) + ->method('getSession') + ->will($this->returnValue($session)); + + $this->controller->Trait->request->expects($this->once()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); + + $this->controller->Trait->expects($this->once()) + ->method('_validateRegisterPost') + ->will($this->returnValue(true)); + + $this->controller->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') + ->setMethods(['identify']) + ->disableOriginalConstructor() + ->getMock(); + + $this->controller->Trait->Auth->expects($this->once()) + ->method('identify'); + + $this->controller->Trait->expects($this->once()) + ->method('_afterIdentifyUser'); + + $this->controller->Trait->socialEmail(); + } +} diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php new file mode 100644 index 000000000..3747ce850 --- /dev/null +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -0,0 +1,243 @@ +traitClassName = 'CakeDC\Users\Controller\Traits\UserValidationTrait'; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; + $this->mockDefaultEmail = true; + parent::setUp(); + } + + /** + * test + * + * @return void + */ + public function testValidateHappyEmail() + { + $this->_mockFlash(); + $user = $this->table->findByToken('token-3')->first(); + $this->assertFalse($user->active); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('User account validated successfully'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->validate('email', 'token-3'); + $user = $this->table->findById($user->id)->first(); + $this->assertTrue($user->active); + } + + /** + * test + * + * @return void + */ + public function testValidateUserNotFound() + { + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Invalid token or user account already validated'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->validate('email', 'not-found'); + } + + /** + * test + * + * @return void + */ + public function testValidateTokenExpired() + { + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Token already expired'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->validate('email', '6614f65816754310a5f0553436dd89e9'); + } + + /** + * test + * + * @return void + */ + public function testValidateTokenExpiredWithOnExpiredEvent() + { + $event = new Event('event'); + $event->result = [ + 'action' => 'newAction', + ]; + $this->Trait->expects($this->once()) + ->method('dispatchEvent') + ->will($this->returnValue($event)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'newAction']); + $this->Trait->validate('email', '6614f65816754310a5f0553436dd89e9'); + } + + /** + * test + * + * @return void + */ + public function testValidateInvalidOp() + { + $this->_mockFlash(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Invalid validation type'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->validate('invalid-op', '6614f65816754310a5f0553436dd89e9'); + } + + /** + * test + * + * @return void + */ + public function testValidateHappyPassword() + { + $this->_mockRequestGet(); + $this->_mockFlash(); + $user = $this->table->findByToken('token-4')->first(); + $this->assertTrue($user->active); + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Reset password token was validated successfully'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'changePassword']); + $this->Trait->validate('password', 'token-4'); + $user = $this->table->findById($user->id)->first(); + $this->assertTrue($user->active); + } + + /** + * test + * + * @return void + */ + public function testResendTokenValidationHappy() + { + $this->_mockRequestPost(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->with('reference') + ->will($this->returnValue('user-3')); + + $this->Trait->Flash->expects($this->once()) + ->method('success') + ->with('Token has been reset successfully. Please check your email.'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->resendTokenValidation(); + } + + /** + * test + * + * @return void + */ + public function testResendTokenValidationWithAfterResendTokenValidationEvent() + { + $this->_mockRequestPost(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->with('reference') + ->will($this->returnValue('user-3')); + + $event = new Event('event'); + $event->result = [ + 'action' => 'newAction', + ]; + $this->Trait->expects($this->once()) + ->method('dispatchEvent') + ->will($this->returnValue($event)); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['action' => 'newAction']); + + $this->Trait->resendTokenValidation(); + } + + /** + * test + * + * @return void + */ + public function testResendTokenValidationAlreadyActive() + { + $this->_mockRequestPost(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->with('reference') + ->will($this->returnValue('user-4')); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('User user-4 is already active'); + $this->Trait->expects($this->never()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->resendTokenValidation(); + } + + /** + * test + * + * @return void + */ + public function testResendTokenValidationNotFound() + { + $this->_mockRequestPost(); + $this->_mockFlash(); + $this->Trait->request->expects($this->once()) + ->method('getData') + ->with('reference') + ->will($this->returnValue('not-found')); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('User not-found was not found'); + $this->Trait->expects($this->never()) + ->method('redirect') + ->with(['action' => 'login']); + $this->Trait->resendTokenValidation(); + } +} diff --git a/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php b/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php new file mode 100644 index 000000000..a42d842f9 --- /dev/null +++ b/tests/TestCase/Exception/AccountAlreadyActiveExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/AccountNotActiveExceptionTest.php b/tests/TestCase/Exception/AccountNotActiveExceptionTest.php new file mode 100644 index 000000000..9e08205d5 --- /dev/null +++ b/tests/TestCase/Exception/AccountNotActiveExceptionTest.php @@ -0,0 +1,45 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/BadConfigurationExceptionTest.php b/tests/TestCase/Exception/BadConfigurationExceptionTest.php new file mode 100644 index 000000000..556b7258f --- /dev/null +++ b/tests/TestCase/Exception/BadConfigurationExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/MissingEmailExceptionTest.php b/tests/TestCase/Exception/MissingEmailExceptionTest.php new file mode 100644 index 000000000..299b51b3f --- /dev/null +++ b/tests/TestCase/Exception/MissingEmailExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/MissingProviderExceptionTest.php b/tests/TestCase/Exception/MissingProviderExceptionTest.php new file mode 100644 index 000000000..0020f3360 --- /dev/null +++ b/tests/TestCase/Exception/MissingProviderExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/TokenExpiredExceptionTest.php b/tests/TestCase/Exception/TokenExpiredExceptionTest.php new file mode 100644 index 000000000..195ae5432 --- /dev/null +++ b/tests/TestCase/Exception/TokenExpiredExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php b/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php new file mode 100644 index 000000000..529742c53 --- /dev/null +++ b/tests/TestCase/Exception/UserAlreadyActiveExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/UserNotActiveExceptionTest.php b/tests/TestCase/Exception/UserNotActiveExceptionTest.php new file mode 100644 index 000000000..73616e68f --- /dev/null +++ b/tests/TestCase/Exception/UserNotActiveExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/UserNotFoundExceptionTest.php b/tests/TestCase/Exception/UserNotFoundExceptionTest.php new file mode 100644 index 000000000..d8e12580c --- /dev/null +++ b/tests/TestCase/Exception/UserNotFoundExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Exception/WrongPasswordExceptionTest.php b/tests/TestCase/Exception/WrongPasswordExceptionTest.php new file mode 100644 index 000000000..20b94bedb --- /dev/null +++ b/tests/TestCase/Exception/WrongPasswordExceptionTest.php @@ -0,0 +1,43 @@ +assertEquals('message', $exception->getMessage()); + } +} diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php new file mode 100644 index 000000000..ae79ca496 --- /dev/null +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -0,0 +1,172 @@ +Email = $this->getMockBuilder('Cake\Mailer\Email') + ->setMethods(['setTo', 'setSubject', 'setViewVars', 'setTemplate']) + ->getMock(); + + $this->UsersMailer = $this->getMockBuilder('CakeDC\Users\Mailer\UsersMailer') + ->setConstructorArgs([$this->Email]) + ->setMethods(['setTo', 'setSubject', 'setViewVars', 'setTemplate']) + ->getMock(); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->UsersMailer); + unset($this->Email); + parent::tearDown(); + } + + /** + * test sendValidationEmail + * + * @return void + */ + public function testValidation() + { + $table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $data = [ + 'first_name' => 'FirstName', + 'email' => 'test@example.com', + 'token' => '12345' + ]; + $user = $table->newEntity($data); + $this->UsersMailer->expects($this->once()) + ->method('setTo') + ->with($user['email']) + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('setSubject') + ->with('FirstName, Your account validation link') + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('setViewVars') + ->with($data) + ->will($this->returnValue($this->Email)); + + $this->invokeMethod($this->UsersMailer, 'validation', [$user]); + } + + /** + * test SocialAccountValidation + * + * @return void + */ + public function testSocialAccountValidation() + { + $social = TableRegistry::getTableLocator()->get('CakeDC/Users.SocialAccounts') + ->get('00000000-0000-0000-0000-000000000001', ['contain' => 'Users']); + + $this->UsersMailer->expects($this->once()) + ->method('setTo') + ->with('user-1@test.com') + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('setSubject') + ->with('first1, Your social account validation link') + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('setViewVars') + ->with(['user' => $social->user, 'socialAccount' => $social]) + ->will($this->returnValue($this->Email)); + + $this->invokeMethod($this->UsersMailer, 'socialAccountValidation', [$social->user, $social]); + } + + /** + * test sendValidationEmail including 'template' + * + * @return void + */ + public function testResetPassword() + { + $table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $data = [ + 'first_name' => 'FirstName', + 'email' => 'test@example.com', + 'token' => '12345' + ]; + $user = $table->newEntity($data); + $this->UsersMailer->expects($this->once()) + ->method('setTo') + ->with($user['email']) + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('setSubject') + ->with('FirstName, Your reset password link') + ->will($this->returnValue($this->Email)); + + $this->Email->expects($this->once()) + ->method('setViewVars') + ->with($data) + ->will($this->returnValue($this->Email)); + + $this->invokeMethod($this->UsersMailer, 'resetPassword', [$user]); + } + + /** + * Call protected/private method of a class. + * + * @param object &$object Instantiated object that we will run method on. + * @param string $methodName Method name to call + * @param array $parameters Array of parameters to pass into method. + * + * @return mixed Method return. + */ + public function invokeMethod(&$object, $methodName, $parameters = []) + { + $reflection = new \ReflectionClass(get_class($object)); + $method = $reflection->getMethod($methodName); + $method->setAccessible(true); + + return $method->invokeArgs($object, $parameters); + } +} diff --git a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php new file mode 100644 index 000000000..2134da7eb --- /dev/null +++ b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php @@ -0,0 +1,104 @@ +table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->Behavior = new AuthFinderBehavior($this->table); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->table, $this->Behavior); + parent::tearDown(); + } + + /** + * Test findActive method. + * + */ + public function testFindActive() + { + $actual = $this->table->find('active')->toArray(); + $this->assertCount(8, $actual); + $this->assertCount(8, Hash::extract($actual, '{n}[active=1]')); + $this->assertCount(0, Hash::extract($actual, '{n}[active=0]')); + } + + /** + * Test findAuth method. + * + * @expectedException \BadMethodCallException + * @expectedExceptionMessage Missing 'username' in options data + */ + public function testFindAuthBadMethodCallException() + { + $user = $this->table->find('auth'); + } + + /** + * Test findAuth method. + * + * @expected + */ + public function testFindAuth() + { + $user = $this->table + ->find('auth', ['username' => 'not-exist@email.com']) + ->toArray(); + $this->assertEmpty($user); + + $user = $this->table + ->find('auth', ['username' => 'user-2@test.com']) + ->first() + ->toArray(); + + $this->assertSame('00000000-0000-0000-0000-000000000002', Hash::get($user, 'id')); + $this->assertSame('user-2', Hash::get($user, 'username')); + } +} diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php new file mode 100644 index 000000000..0d2710ae0 --- /dev/null +++ b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php @@ -0,0 +1,363 @@ +Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->Behavior = new LinkSocialBehavior($this->Table); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->Table, $this->Behavior); + parent::tearDown(); + } + + /** + * Test linkSocialAccount with facebook and not existing social account + * + * @param array $data Test input data + * @param string $userId User id to add social account + * @param array $result Expected result + * + * @author Marcelo Rocha + * @return void + * @dataProvider providerFacebookLinkSocialAccount + */ + public function testlinkSocialAccountFacebookProvider($data, $userId, $result) + { + $user = $this->Table->get($userId, [ + 'contain' => 'SocialAccounts' + ]); + $resultUser = $this->Behavior->linkSocialAccount($user, $data); + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); + $actual = $resultUser->social_accounts[2]; + + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\SocialAccount', $actual); + $actual->token_expires = $actual->token_expires->format('Y-m-d H:i:s'); + + foreach ($result as $property => $value) { + $this->assertEquals($value, $actual->$property); + } + + $result = $this->Table->SocialAccounts->exists(['id' => $actual->id]); + $this->assertTrue($result); + } + + /** + * Provider for linkSocialAccount with facebook and not existing social account + * + * @author Marcelo Rocha + * @return array + */ + public function providerFacebookLinkSocialAccount() + { + $expiresTime = new Time(); + $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); + + return [ + 'provider' => [ + 'data' => [ + 'id' => '9999911112255', //Reference existe mas provider google + 'username' => null, + 'full_name' => 'Full name', + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'raw' => [ + 'id' => '9999911112255', + 'name' => 'Ful Name.', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'picture' => [ + 'data' => [ + 'url' => 'data-url' + ] + ] + ], + 'credentials' => [ + 'token' => 'token', + 'secret' => null, + 'expires' => 1458423682 + ], + 'validated' => true, + 'link' => 'facebook-link-15579', + 'provider' => 'Facebook' + ], + 'user' => '00000000-0000-0000-0000-000000000001', + 'result' => [ + 'provider' => 'Facebook', + 'username' => null, + 'reference' => '9999911112255', + 'avatar' => '', + 'link' => 'facebook-link-15579', + 'description' => null, + 'token' => 'token', + 'token_secret' => null, + 'token_expires' => $tokenExpires, + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'active' => true + + ] + ] + + ]; + } + + /** + * Test linkSocialAccount with facebook and could not save social account + * + * @param array $data Test input data + * @param string $userId User id to add social account + * @param array $result Expected result + * + * @author Marcelo Rocha + * @return void + * @dataProvider providerFacebookLinkSocialAccountErrorSaving + */ + public function testlinkSocialAccountErrorSavingFacebookProvider($data, $userId, $result) + { + $user = $this->Table->get($userId); + $resultUser = $this->Behavior->linkSocialAccount($user, $data); + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); + $actual = $resultUser->social_accounts[0]; + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\SocialAccount', $actual); + + $actual = $user->getErrors(); + + $expected = [ + 'social_accounts' => [ + [ + 'token' => [ + '_empty' => 'This field cannot be left empty' + ] + ] + ] + ]; + $this->assertEquals($expected, $actual); + + $error = $user->getErrors('social_accounts'); + $error = $error ? reset($error) : $message; + } + + /** + * Provider for linkSocialAccount with facebook and could not save social account + * + * @author Marcelo Rocha + * @return array + */ + public function providerFacebookLinkSocialAccountErrorSaving() + { + $expiresTime = new Time(); + $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); + + return [ + 'provider' => [ + 'data' => [ + 'id' => '9999911112255', //Reference existe mas provider google + 'username' => null, + 'full_name' => 'Full name', + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'raw' => [ + 'id' => '9999911112255', + 'name' => 'Ful Name.', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'user-1@test.com', + 'picture' => [ + 'data' => [ + 'url' => 'data-url' + ] + ] + ], + 'credentials' => [ + 'token' => '', + 'secret' => null, + 'expires' => 1458423682 + ], + 'validated' => true, + 'link' => 'facebook-link-15579', + 'provider' => 'Facebook' + ], + 'user' => '00000000-0000-0000-0000-000000000001', + 'result' => [ + 'provider' => 'Facebook', + 'username' => null, + 'reference' => '9999911112255', + 'avatar' => '', + 'link' => 'facebook-link-15579', + 'description' => null, + 'token' => 'token', + 'token_secret' => null, + 'token_expires' => $tokenExpires, + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'active' => true + + ] + ] + + ]; + } + + /** + * Test linkSocialAccount with facebook when account already exists + * + * @param array $data Test input data + * @param string $userId User id to add social account + * @param array $result Expected result + * + * @author Marcelo Rocha + * @return void + * @dataProvider providerFacebookLinkSocialAccountAccountExists + */ + public function testlinkSocialAccountFacebookProviderAccountExists($data, $userId, $result) + { + $user = $this->Table->get($userId); + $resultUser = $this->Behavior->linkSocialAccount($user, $data); + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); + $this->assertFalse($resultUser->has('social_accounts')); + $expected = [ + 'social_accounts' => [ + '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') + ] + ]; + $actual = $user->getErrors(); + $this->assertEquals($expected, $actual); + + //Se for o usuĆ”rio que jĆ” esta associado entĆ£o okay + $socialAccount = $this->Table->SocialAccounts->find()->where([ + 'reference' => $data['id'], + 'provider' => $data['provider'] + ])->firstOrFail(); + + $userBase = $this->Table->get('00000000-0000-0000-0000-000000000002', [ + 'contain' => ['SocialAccounts'] + ]); + $resultUser = $this->Behavior->linkSocialAccount($userBase, $data); + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\User', $resultUser); + $this->assertEquals([], $userBase->getErrors()); + + $actual = $resultUser->social_accounts[0]; + + $this->assertInstanceOf('\CakeDC\Users\Model\Entity\SocialAccount', $actual); + + $actual->token_expires = $actual->token_expires->format('Y-m-d H:i:s'); + foreach ($result as $property => $value) { + $this->assertEquals($value, $actual->$property); + } + } + + /** + * Provider for linkSocialAccount with facebook when account already exists + * + * @author Marcelo Rocha + * @return array + */ + public function providerFacebookLinkSocialAccountAccountExists() + { + $expiresTime = new Time(); + $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); + + return [ + 'provider' => [ + 'data' => [ + 'id' => 'reference-2-1', + 'username' => null, + 'full_name' => 'Full name', + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'email' => 'email@example.com', + 'raw' => [ + 'id' => 'reference-2-1', + 'name' => 'Ful Name.', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'email@example.com', + 'picture' => [ + 'data' => [ + 'url' => 'data-url' + ] + ] + ], + 'credentials' => [ + 'token' => 'token', + 'secret' => null, + 'expires' => 1458423682 + ], + 'validated' => true, + 'link' => 'facebook-link-15579', + 'provider' => 'Facebook' + ], + 'user' => '00000000-0000-0000-0000-000000000001', + 'result' => [ + 'id' => '00000000-0000-0000-0000-000000000003', + 'provider' => 'Facebook', + 'username' => null, + 'reference' => 'reference-2-1', + 'avatar' => '', + 'link' => 'facebook-link-15579', + 'description' => null, + 'token' => 'token', + 'token_secret' => null, + 'token_expires' => $tokenExpires, + 'user_id' => '00000000-0000-0000-0000-000000000002', + 'active' => true + ] + ] + + ]; + } +} diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php new file mode 100644 index 000000000..d25bac7aa --- /dev/null +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -0,0 +1,237 @@ +table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\PasswordBehavior') + ->setMethods(['_sendResetPasswordEmail']) + ->setConstructorArgs([$this->table]) + ->getMock(); + Email::setConfigTransport('test', [ + 'className' => 'Debug' + ]); + //$this->configEmail = Email::getConfig('default'); + Email::setConfig('default', [ + 'transport' => 'test', + 'from' => 'cakedc@example.com' + ]); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->table, $this->Behavior); + Email::drop('default'); + Email::dropTransport('test'); + parent::tearDown(); + } + + /** + * Test resetToken + * + */ + public function testResetToken() + { + $user = $this->table->findByUsername('user-1')->first(); + $token = $user->token; + $this->Behavior->expects($this->never()) + ->method('_sendResetPasswordEmail') + ->with($user); + $result = $this->Behavior->resetToken('user-1', [ + 'expiration' => 3600, + 'checkActive' => true, + ]); + $this->assertNotEquals($token, $result->token); + $this->assertEmpty($result->activation_date); + $this->assertFalse($result->active); + } + + /** + * Test resetToken + * + */ + public function testResetTokenSendEmail() + { + $user = $this->table->findByUsername('user-1')->first(); + $token = $user->token; + $tokenExpires = $user->token_expires; + $this->Behavior->expects($this->once()) + ->method('_sendResetPasswordEmail'); + $result = $this->Behavior->resetToken('user-1', [ + 'expiration' => 3600, + 'checkActive' => true, + 'sendEmail' => true, + 'type' => 'password' + ]); + $this->assertNotEquals($token, $result->token); + $this->assertNotEquals($tokenExpires, $result->token_expires); + $this->assertEmpty($result->activation_date); + $this->assertFalse($result->active); + } + + /** + * Test resetToken + * + * @expectedException InvalidArgumentException + */ + public function testResetTokenWithNullParams() + { + $this->Behavior->resetToken(null); + } + + /** + * Test resetTokenNoExpiration + * + * @expectedException InvalidArgumentException + * @expectedExceptionMessage Token expiration cannot be empty + */ + public function testResetTokenNoExpiration() + { + $this->Behavior->resetToken('ref'); + } + + /** + * Test resetToken + * + * @expectedException \CakeDC\Users\Exception\UserNotFoundException + */ + public function testResetTokenNotExistingUser() + { + $this->Behavior->resetToken('user-not-found', [ + 'expiration' => 3600 + ]); + } + + /** + * Test resetToken + * + * @expectedException \CakeDC\Users\Exception\UserAlreadyActiveException + */ + public function testResetTokenUserAlreadyActive() + { + $activeUser = TableRegistry::getTableLocator()->get('CakeDC/Users.Users')->findByUsername('user-4')->first(); + $this->assertTrue($activeUser->active); + $this->table = $this->getMockForModel('CakeDC/Users.Users', ['save']); + $this->table->expects($this->never()) + ->method('save'); + $this->Behavior->expects($this->never()) + ->method('_sendResetPasswordEmail'); + $this->Behavior->resetToken('user-4', [ + 'expiration' => 3600, + 'checkActive' => true, + ]); + } + + /** + * Test resetToken + * + * @expectedException \CakeDC\Users\Exception\UserNotActiveException + */ + public function testResetTokenUserNotActive() + { + $user = $this->table->findByUsername('user-1')->first(); + $this->Behavior->resetToken('user-1', [ + 'ensureActive' => true, + 'expiration' => 3600 + ]); + } + + /** + * Test resetToken + */ + public function testResetTokenUserActive() + { + $user = TableRegistry::getTableLocator()->get('CakeDC/Users.Users')->findByUsername('user-2')->first(); + $result = $this->Behavior->resetToken('user-2', [ + 'ensureActive' => true, + 'expiration' => 3600 + ]); + $this->assertEquals($user->id, $result->id); + } + + /** + * Test changePassword + */ + public function testChangePassword() + { + $user = TableRegistry::getTableLocator()->get('CakeDC/Users.Users')->findByUsername('user-6')->first(); + $user->current_password = '12345'; + $user->password = 'new'; + $user->password_confirmation = 'new'; + + $result = $this->Behavior->changePassword($user); + } + + /** + * test Email Override + */ + public function testEmailOverride() + { + $overrideMailer = $this->getMockBuilder(OverrideMailer::class) + ->setMethods(['send']) + ->getMock(); + Configure::write('Users.Email.mailerClass', OverrideMailer::class); + $this->Behavior = $this->getMockBuilder(PasswordBehavior::class) + ->setConstructorArgs([$this->table]) + ->setMethods(['getMailer']) + ->getMock(); + $overrideMailer->expects($this->once()) + ->method('send') + ->with('resetPassword') + ->willReturn(true); + $this->Behavior->expects($this->once()) + ->method('getMailer') + ->with(OverrideMailer::class) + ->willReturn($overrideMailer); + $this->Behavior->resetToken('user-1', [ + 'expiration' => 3600, + 'checkActive' => true, + 'sendEmail' => true, + 'type' => 'password' + ]); + } +} diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php new file mode 100644 index 000000000..0dfa3ffdf --- /dev/null +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -0,0 +1,320 @@ +get('CakeDC/Users.Users'); + $table->addBehavior('CakeDC/Users/Register.Register'); + $this->Table = $table; + $this->Behavior = $table->behaviors()->Register; + Email::setConfigTransport('test', [ + 'className' => 'Debug' + ]); + Email::setConfig('default', [ + 'transport' => 'test', + 'from' => 'cakedc@example.com' + ]); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->Table, $this->Behavior); + Email::drop('default'); + Email::dropTransport('test'); + parent::tearDown(); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterNoValidateEmail() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 0]); + $this->assertTrue($result->active); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterEmptyUser() + { + $user = []; + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $this->assertFalse($result); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterValidateEmailAndTos() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $this->assertNotEmpty($result); + $this->assertFalse($result->active); + $this->assertNotEmpty($result->tos_date); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterValidatorOption() + { + $this->Table = $this->getMockForModel('CakeDC/Users.Users', ['validationCustom', 'patchEntity', 'errors', 'save']); + + $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\RegisterBehavior') + ->setMethods(['getValidators', '_updateActive']) + ->setConstructorArgs([$this->Table]) + ->getMock(); + + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + + $this->Behavior->expects($this->never()) + ->method('getValidators'); + + $entityUser = $this->Table->newEntity($user); + + $this->Behavior->expects($this->once()) + ->method('_updateActive') + ->will($this->returnValue($entityUser)); + + $this->Table->expects($this->once()) + ->method('patchEntity') + ->with($this->Table->newEntity(), $user, ['validate' => 'custom']) + ->will($this->returnValue($entityUser)); + + $this->Table->expects($this->once()) + ->method('save') + ->with($entityUser) + ->will($this->returnValue($entityUser)); + + $result = $this->Behavior->register($this->Table->newEntity(), $user, ['validator' => 'custom', 'validate_email' => 1]); + $this->assertNotEmpty($result->tos_date); + } + + /** + * Test register method + * + */ + public function testValidateRegisterTosRequired() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + ]; + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); + $this->assertFalse($result); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterNoTosRequired() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + ]; + $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); + $this->assertNotEmpty($result); + } + + /** + * Test ActivateUser method + * + * @return void + */ + public function testActivateUser() + { + $user = $this->Table->find()->where(['id' => '00000000-0000-0000-0000-000000000001'])->first(); + $result = $this->Table->activateUser($user); + $this->assertTrue($result->active); + } + + /** + * Test Validate method + * + * @return void + */ + public function testValidate() + { + $result = $this->Table->validate('ae93ddbe32664ce7927cf0c5c5a5e59d', 'activateUser'); + $this->assertTrue($result->active); + $this->assertEmpty($result->token_expires); + } + + /** + * Test Validate method + * + * @return void + * @expectedException \CakeDC\Users\Exception\TokenExpiredException + */ + public function testValidateUserWithExpiredToken() + { + $this->Table->validate('token-5', 'activateUser'); + } + + /** + * Test Validate method + * + * @return void + * @expectedException \CakeDC\Users\Exception\UserNotFoundException + */ + public function testValidateNotExistingUser() + { + $this->Table->validate('not-existing-token', 'activateUser'); + } + + /** + * Test activateUser method + * + * @return void + */ + public function testActiveUserRemoveValidationToken() + { + $user = $this->Table->find()->where(['id' => '00000000-0000-0000-0000-000000000001'])->first(); + $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\RegisterBehavior') + ->setConstructorArgs([$this->Table]) + ->getMock(); + + $resultValidationToken = $user; + $resultValidationToken->token_expires = null; + $resultValidationToken->token = null; + + $this->Behavior->activateUser($user); + } + + /** + * Test register default role + * + * @return void + */ + public function testRegisterUsingDefaultRole() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + Configure::write('Users.Registration.defaultRole', false); + $result = $this->Table->register($this->Table->newEntity(), $user, [ + 'token_expiration' => 3600, + 'validate_email' => 0 + ]); + $this->assertSame('user', $result['role']); + } + + /** + * Test register not default role + * + * @return void + */ + public function testRegisterUsingCustomRole() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + Configure::write('Users.Registration.defaultRole', 'emperor'); + $result = $this->Table->register($this->Table->newEntity(), $user, [ + 'token_expiration' => 3600, + 'validate_email' => 0, + ]); + $this->assertSame('emperor', $result['role']); + } +} diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php new file mode 100644 index 000000000..b9149c516 --- /dev/null +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -0,0 +1,141 @@ +Table = TableRegistry::getTableLocator()->get('CakeDC/Users.SocialAccounts'); + $this->Behavior = $this->Table->behaviors()->SocialAccount; + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->Table, $this->Behavior, $this->Email); + parent::tearDown(); + } + + /** + * Test validateEmail method + * + * @return void + */ + public function testValidateEmail() + { + $token = 'token-1234'; + $result = $this->Behavior->validateAccount(SocialAccountsTable::PROVIDER_FACEBOOK, 'reference-1-1234', $token); + $this->assertTrue($result->active); + $this->assertEquals($token, $result->token); + } + + /** + * Test validateEmail method + * + * @expectedException \Cake\Datasource\Exception\RecordNotFoundException + */ + public function testValidateEmailInvalidToken() + { + $this->Behavior->validateAccount(1, 'reference-1234', 'invalid-token'); + } + + /** + * Test validateEmail method + * + * @expectedException \Cake\Datasource\Exception\RecordNotFoundException + */ + public function testValidateEmailInvalidUser() + { + $this->Behavior->validateAccount(1, 'invalid-user', 'token-1234'); + } + + /** + * Test validateEmail method + * + * @expectedException CakeDC\Users\Exception\AccountAlreadyActiveException + */ + public function testValidateEmailActiveAccount() + { + $this->Behavior->validateAccount(SocialAccountsTable::PROVIDER_TWITTER, 'reference-1-1234', 'token-1234'); + } + + /** + * testAfterSaveSocialNotActiveUserNotActive + * don't send email, user is not active + * + * @return void + */ + public function testAfterSaveSocialNotActiveUserNotActive() + { + $event = new Event('eventName'); + $entity = $this->Table->find()->first(); + $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); + } + + /** + * testAfterSaveSocialActiveUserActive + * social account is active, don't send email + * + * @return void + */ + public function testAfterSaveSocialActiveUserActive() + { + $event = new Event('eventName'); + $entity = $this->Table->findById('00000000-0000-0000-0000-000000000003')->first(); + $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); + } + + /** + * testAfterSaveSocialActiveUserNotActive + * social account is active, don't send email + * + * @return void + */ + public function testAfterSaveSocialActiveUserNotActive() + { + $event = new Event('eventName'); + $entity = $this->Table->findById('00000000-0000-0000-0000-000000000002')->first(); + $this->assertTrue($this->Behavior->afterSave($event, $entity, [])); + } +} diff --git a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php new file mode 100644 index 000000000..0582eac9b --- /dev/null +++ b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php @@ -0,0 +1,388 @@ +Table = $this->getMockForModel('CakeDC/Users.Users', ['save']); + $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialBehavior') + ->setMethods(['randomString', '_updateActive', 'generateUniqueUsername']) + ->setConstructorArgs([$this->Table]) + ->getMock(); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + unset($this->Table, $this->Behavior, $this->Email); + parent::tearDown(); + } + + /** + * Test socialLogin with facebook and not existing user + * + * @dataProvider providerFacebookSocialLogin + */ + public function testSocialLoginFacebookProvider($data, $options, $dataUser) + { + $user = $this->Table->newEntity($dataUser, ['associated' => ['SocialAccounts']]); + $user->password = '$2y$10$0QzszaIEpW1pYpoKJVf4DeqEAHtg9whiLTX/l3TcHAoOLF1bC9U.6'; + + $this->Behavior->expects($this->once()) + ->method('generateUniqueUsername') + ->with('email') + ->will($this->returnValue('username')); + + $this->Behavior->expects($this->once()) + ->method('randomString') + ->will($this->returnValue('password')); + + $this->Behavior->expects($this->once()) + ->method('_updateActive') + ->will($this->returnValue($user)); + + $this->Table->expects($this->once()) + ->method('save') + ->with($user) + ->will($this->returnValue($user)); + + $result = $this->Behavior->socialLogin($data, $options); + $this->assertEquals($result, $user); + } + + /** + * Test socialLogin with facebook and not existing user + * + * @dataProvider providerFacebookSocialLogin + */ + public function testSocialLoginFacebookProviderUsingEmail($data, $options, $dataUser) + { + $user = $this->Table->newEntity($dataUser, ['associated' => ['SocialAccounts']]); + $user->password = '$2y$10$0QzszaIEpW1pYpoKJVf4DeqEAHtg9whiLTX/l3TcHAoOLF1bC9U.6'; + + $this->Behavior->expects($this->once()) + ->method('generateUniqueUsername') + ->with('email') + ->will($this->returnValue('username')); + + $this->Behavior->expects($this->once()) + ->method('randomString') + ->will($this->returnValue('password')); + + $this->Behavior->expects($this->once()) + ->method('_updateActive') + ->will($this->returnValue($user)); + + $this->Table->expects($this->once()) + ->method('save') + ->with($user) + ->will($this->returnValue($user)); + + $this->Behavior->initialize(['username' => 'email']); + $result = $this->Behavior->socialLogin($data, $options); + $this->assertEquals($result, $user); + } + + /** + * Provider for socialLogin with facebook and not existing user + * + */ + public function providerFacebookSocialLogin() + { + return [ + 'provider' => [ + 'data' => [ + 'id' => 'facebook-id', + 'username' => null, + 'full_name' => 'Full name', + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'email' => 'email@example.com', + 'raw' => [ + 'id' => '10153521527396318', + 'name' => 'Ful Name.', + 'first_name' => 'First Name', + 'last_name' => 'Last name', + 'email' => 'email@example.com', + 'picture' => [ + 'data' => [ + 'url' => 'data-url' + ] + ] + ], + 'credentials' => [ + 'token' => 'token', + 'secret' => null, + 'expires' => 1458423682 + ], + 'validated' => true, + 'link' => 'facebook-link', + 'provider' => 'Facebook' + ], + 'options' => [ + 'use_email' => true, + 'validate_email' => true, + 'token_expiration' => 3600 + ], + 'result' => [ + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'username' => 'username', + 'email' => 'email@example.com', + 'password' => '$2y$10$oLPxCkKJ1TUCR6xJ1t0Wj.7Fznx49Wn4NZB2aJCmVvRMucaHuNyyO', + 'avatar' => null, + 'tos_date' => '2016-01-20 15:45:09', + 'gender' => null, + 'social_accounts' => [ + [ + 'provider' => 'Facebook', + 'username' => null, + 'reference' => '10153521527396318', + 'avatar' => '', + 'link' => 'facebook-link', + 'description' => null, + 'token' => 'token', + 'token_secret' => null, + 'token_expires' => '2016-03-19 21:41:22', + 'data' => '-', + 'active' => true + ] + ], + 'activation_date' => '2016-01-20 15:45:09', + 'active' => true, + ] + ] + + ]; + } + + /** + * Test socialLogin with facebook with existing and active user + * + * @dataProvider providerFacebookSocialLoginExistingReference + */ + public function testSocialLoginExistingReference($data, $options) + { + $this->Behavior->expects($this->never()) + ->method('generateUniqueUsername'); + + $this->Behavior->expects($this->never()) + ->method('randomString'); + + $this->Behavior->expects($this->never()) + ->method('_updateActive'); + + $result = $this->Behavior->socialLogin($data, $options); + $this->assertEquals($result->id, '00000000-0000-0000-0000-000000000002'); + $this->assertTrue($result->active); + } + + /** + * Provider for socialLogin with facebook with existing and active user + * + */ + public function providerFacebookSocialLoginExistingReference() + { + return [ + 'provider' => [ + 'data' => [ + 'id' => 'reference-2-1', + 'provider' => 'Facebook' + ], + 'options' => [ + 'use_email' => true, + 'validate_email' => true, + 'token_expiration' => 3600 + ], + ] + + ]; + } + + /** + * Test socialLogin with existing and active user and not active social account + * + * @expectedException CakeDC\Users\Exception\AccountNotActiveException + * @dataProvider providerSocialLoginExistingAndNotActiveAccount + */ + public function testSocialLoginExistingNotActiveReference($data, $options) + { + $this->Behavior->expects($this->never()) + ->method('generateUniqueUsername'); + + $this->Behavior->expects($this->never()) + ->method('randomString'); + + $this->Behavior->expects($this->never()) + ->method('_updateActive'); + $this->Behavior->socialLogin($data, $options); + } + + /** + * Provider for socialLogin with existing and active user and not active social account + * + */ + public function providerSocialLoginExistingAndNotActiveAccount() + { + return [ + 'provider' => [ + 'data' => [ + 'id' => 'reference-1-1234', + 'provider' => 'Facebook' + ], + 'options' => [ + 'use_email' => true, + 'validate_email' => true, + 'token_expiration' => 3600 + ], + ] + + ]; + } + + /** + * Test socialLogin with existing and active account but not active user + * + * @expectedException CakeDC\Users\Exception\UserNotActiveException + * @dataProvider providerSocialLoginExistingAccountNotActiveUser + */ + public function testSocialLoginExistingReferenceNotActiveUser($data, $options) + { + $this->Behavior->expects($this->never()) + ->method('generateUniqueUsername'); + + $this->Behavior->expects($this->never()) + ->method('randomString'); + + $this->Behavior->expects($this->never()) + ->method('_updateActive'); + $this->Behavior->socialLogin($data, $options); + } + + /** + * Provider for socialLogin with existing and active account but not active user + * + */ + public function providerSocialLoginExistingAccountNotActiveUser() + { + return [ + 'provider' => [ + 'data' => [ + 'id' => 'reference-1-1234', + 'provider' => 'Twitter' + ], + 'options' => [ + 'use_email' => true, + 'validate_email' => true, + 'token_expiration' => 3600 + ], + ] + + ]; + } + + /** + * Test socialLogin with facebook and not existing user + * + * @dataProvider providerFacebookSocialLoginNoEmail + * @expectedException CakeDC\Users\Exception\MissingEmailException + */ + public function testSocialLoginNoEmail($data, $options) + { + $this->Behavior->socialLogin($data, $options); + } + + /** + * Provider for socialLogin with facebook and not existing user + * + */ + public function providerFacebookSocialLoginNoEmail() + { + return [ + 'provider' => [ + 'data' => [ + 'id' => 'facebook-id', + 'username' => null, + 'full_name' => 'Full name', + 'first_name' => 'First name', + 'last_name' => 'Last name', + 'validated' => true, + 'link' => 'facebook-link', + 'provider' => 'Facebook' + ], + 'options' => [ + 'use_email' => true, + 'validate_email' => true, + 'token_expiration' => 3600 + ], + ] + + ]; + } + + /** + * Test socialLogin with facebook and not existing user + * + * @dataProvider providerGenerateUsername + */ + public function testGenerateUniqueUsername($param, $expected) + { + $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialBehavior') + ->setMethods(['randomString', '_updateActive']) + ->setConstructorArgs([$this->Table]) + ->getMock(); + + $result = $this->Behavior->generateUniqueUsername($param); + $this->assertEquals($expected, $result); + } + + /** + * Provider for socialLogin with facebook and not existing user + * + */ + public function providerGenerateUsername() + { + return [ + ['username', 'username'], + ['user-1', 'user-10'], + ['user-5', 'user-50'] + + ]; + } +} diff --git a/tests/TestCase/Model/Entity/UserTest.php b/tests/TestCase/Model/Entity/UserTest.php new file mode 100644 index 000000000..03165a769 --- /dev/null +++ b/tests/TestCase/Model/Entity/UserTest.php @@ -0,0 +1,206 @@ +now = Time::now(); + Time::setTestNow($this->now); + $this->User = new User(); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + unset($this->User); + Time::setTestNow(); + + parent::tearDown(); + } + + /** + * Test tokenExpired method + * + * @return void + */ + public function testTokenExpiredEmpty() + { + $this->User->token_expires = null; + $isExpired = $this->User->tokenExpired(); + $this->assertTrue($isExpired); + } + + /** + * Test tokenExpired method + * + * @return void + */ + public function testTokenExpiredNotYet() + { + $this->User->token_expires = '-1 day'; + $isExpired = $this->User->tokenExpired(); + $this->assertTrue($isExpired); + } + + /** + * Test tokenExpired method + * + * @return void + */ + public function testTokenExpired() + { + $this->User->token_expires = '+1 day'; + $isExpired = $this->User->tokenExpired(); + $this->assertFalse($isExpired); + } + + /** + * Test tokenExpired another locale + * + * @return void + */ + public function testTokenExpiredLocale() + { + I18n::setLocale('es_AR'); + $this->User->token_expires = '+1 day'; + $isExpired = $this->User->tokenExpired(); + $this->assertFalse($isExpired); + $this->User->token_expires = '-1 day'; + $isExpired = $this->User->tokenExpired(); + $this->assertTrue($isExpired); + I18n::setLocale('en_US'); + } + + /** + * test + * + * @return void + */ + public function testPasswordsAreEncrypted() + { + $pw = 'password'; + $this->User->password = $pw; + $this->assertTrue((new DefaultPasswordHasher)->check($pw, $this->User->password)); + } + + public function testConfirmPasswordsAreEncrypted() + { + $pw = 'password'; + $this->User->confirm_password = $pw; + $this->assertTrue((new DefaultPasswordHasher)->check($pw, $this->User->confirm_password)); + } + + /** + * test + * + * @return void + */ + public function testCheckPassword() + { + $pw = 'password'; + $this->assertTrue($this->User->checkPassword($pw, (new DefaultPasswordHasher)->hash($pw))); + $this->assertFalse($this->User->checkPassword($pw, 'fail')); + } + + /** + * test + * + * @return void + */ + public function testGetAvatar() + { + $this->assertNull($this->User->avatar); + $avatar = 'first-avatar'; + $this->User->social_accounts = [ + ['avatar' => 'first-avatar'], + ['avatar' => 'second-avatar'] + ]; + $this->assertSame($avatar, $this->User->avatar); + } + + /** + * test + * + * @return void + */ + public function testUpdateToken() + { + $this->assertNull($this->User['token']); + $this->assertNull($this->User['token_expires']); + $this->User->updateToken(); + $this->assertEquals($this->now, $this->User['token_expires']); + $this->assertNotNull($this->User['token']); + } + + /** + * test + * + * @return void + */ + public function testUpdateTokenExisting() + { + $this->User['token'] = 'aaa'; + $this->User['token_expires'] = $this->now; + $this->User->updateToken(); + $this->assertEquals($this->now, $this->User['token_expires']); + $this->assertNotEquals('aaa', $this->User['token']); + } + + /** + * test + * + * @return void + */ + public function testUpdateTokenAdd() + { + $this->assertNull($this->User['token']); + $this->assertNull($this->User['token_expires']); + $this->User->updateToken(20); + $this->assertEquals('20 seconds after', $this->User['token_expires']->diffForHumans($this->now)); + $this->assertNotNull($this->User['token']); + } + + /** + * test + * + * @return void + */ + public function testUpdateTokenExistingAdd() + { + $this->User['token'] = 'aaa'; + $this->User['token_expires'] = $this->now; + $this->User->updateToken(20); + $this->assertEquals('20 seconds after', $this->User['token_expires']->diffForHumans($this->now)); + $this->assertNotEquals('aaa', $this->User['token']); + } +} diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php new file mode 100644 index 000000000..f662d7bf2 --- /dev/null +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -0,0 +1,74 @@ +SocialAccounts = TableRegistry::getTableLocator()->get('CakeDC/Users.SocialAccounts'); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + unset($this->SocialAccounts); + + parent::tearDown(); + } + + public function testValidationHappy() + { + $data = [ + 'provider' => 'Facebook', + 'reference' => 'test-reference', + 'link' => 'test-link', + 'token' => 'test-token', + 'active' => 0, + 'data' => 'test-data', + ]; + $entity = $this->SocialAccounts->newEntity($data); + $this->assertEmpty($entity->getErrors()); + } +} diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php new file mode 100644 index 000000000..03b91b37e --- /dev/null +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -0,0 +1,312 @@ +Users = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->fullBaseBackup = Router::fullBaseUrl(); + Router::fullBaseUrl('http://users.test'); + Email::setConfigTransport('test', [ + 'className' => 'Debug' + ]); + Email::setConfig('default', [ + 'transport' => 'test', + 'from' => 'cakedc@example.com' + ]); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + unset($this->Users); + Router::fullBaseUrl($this->fullBaseBackup); + Email::drop('default'); + Email::dropTransport('test'); + + parent::tearDown(); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterNoValidateEmail() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 0]); + $this->assertTrue($result->active); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterEmptyUser() + { + $user = []; + $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $this->assertFalse($result); + } + + /** + * Test register method + * + * @return void + */ + public function testValidateRegisterValidateEmail() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + 'tos' => 1 + ]; + $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $this->assertNotEmpty($result); + $this->assertFalse($result->active); + } + + /** + * test + */ + public function testValidateRegisterTosRequired() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + ]; + $userEntity = $this->Users->newEntity(); + $this->Users->register($userEntity, $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); + $this->assertEquals(['tos' => ['_required' => 'This field is required']], $userEntity->getErrors()); + } + + /** + * Test register method + * testValidateRegisterValidateEmail + */ + public function testValidateRegisterNoTosRequired() + { + $user = [ + 'username' => 'testuser', + 'email' => 'testuser@test.com', + 'password' => 'password', + 'password_confirm' => 'password', + 'first_name' => 'test', + 'last_name' => 'user', + ]; + $result = $this->Users->register($this->Users->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); + $this->assertNotEmpty($result); + } + + /** + * Test ActivateUser method + * + * @return void + */ + public function testActivateUser() + { + $user = $this->Users->find()->where(['id' => '00000000-0000-0000-0000-000000000001'])->first(); + $result = $this->Users->activateUser($user); + $this->assertTrue($result->active); + } + + public function testSocialLogin() + { + $data = [ + 'provider' => SocialAccountsTable::PROVIDER_FACEBOOK, + 'email' => 'user-2@test.com', + 'id' => 'reference-2-1', + 'link' => 'link', + 'raw' => [ + 'id' => 'reference-2-1', + 'token' => 'token', + 'first_name' => 'User 2', + 'gender' => 'female', + 'verified' => 1, + 'user_email' => 'user-2@test.com', + 'link' => 'link' + ] + ]; + $options = [ + 'use_email' => 1, + 'validate_email' => 1, + 'token_expiration' => 3600 + ]; + $result = $this->Users->socialLogin($data, $options); + $this->assertEquals('user-2@test.com', $result->email); + $this->assertTrue($result->active); + } + + /** + * Test socialLogin + * + * @expectedException CakeDC\Users\Exception\AccountNotActiveException + */ + public function testSocialLoginInactiveAccount() + { + $data = [ + 'provider' => SocialAccountsTable::PROVIDER_TWITTER, + 'email' => 'hello@test.com', + 'id' => 'reference-2-2', + 'link' => 'link', + 'raw' => [ + 'id' => 'reference-2-2', + 'first_name' => 'User 2', + 'gender' => 'female', + 'verified' => 1, + 'user_email' => 'hello@test.com', + ] + ]; + $options = [ + 'use_email' => 1, + 'validate_email' => 1, + 'token_expiration' => 3600 + ]; + $result = $this->Users->socialLogin($data, $options); + $this->assertEquals('user-2@test.com', $result->email); + $this->assertFalse($result->active); + } + + /** + * Test socialLogin + * + * @expectedException InvalidArgumentException + */ + public function testSocialLoginCreateNewAccountWithNoCredentials() + { + $data = [ + 'provider' => SocialAccountsTable::PROVIDER_TWITTER, + 'email' => 'user@test.com', + 'id' => 'reference-not-existing', + 'link' => 'link', + 'raw' => [ + 'id' => 'reference-not-existing', + 'first_name' => 'Not existing user', + 'gender' => 'male', + 'user_email' => 'user@test.com', + ], + 'credentials' => [], + 'name' => '', + ]; + + $options = [ + 'use_email' => 0, + 'validate_email' => 1, + 'token_expiration' => 3600 + ]; + $result = $this->Users->socialLogin($data, $options); + $this->assertFalse($result); + } + + /** + * Test socialLogin + * + */ + public function testSocialLoginCreateNewAccount() + { + $data = [ + 'provider' => SocialAccountsTable::PROVIDER_TWITTER, + 'email' => 'username@test.com', + 'id' => 'no-existing-reference', + 'link' => 'link', + 'first_name' => 'First Name', + 'last_name' => 'Last Name', + 'raw' => [ + 'id' => 'no-existing-reference', + 'first_name' => 'First Name', + 'last_name' => 'Last Name', + 'gender' => 'male', + 'user_email' => 'user@test.com', + 'twitter' => 'link' + ], + 'info' => [ + 'first_name' => 'First Name', + 'last_name' => 'Last Name', + 'urls' => ['twitter' => 'twitter'] + ], + 'validated' => true, + 'credentials' => [ + 'token' => 'token', + 'token_secret' => 'secret', + 'token_expires' => '' + ], + ]; + + $options = [ + 'use_email' => 0, + 'validate_email' => 0, + 'token_expiration' => 3600 + ]; + $result = $this->Users->socialLogin($data, $options); + $this->assertNotEmpty($result); + $this->assertEquals('no-existing-reference', $result->social_accounts[0]->reference); + $this->assertEquals(1, count($result->social_accounts)); + $this->assertEquals('username', $result->username); + $this->assertEquals('First Name', $result->first_name); + $this->assertEquals('Last Name', $result->last_name); + } +} diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php new file mode 100644 index 000000000..05bd3e58f --- /dev/null +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -0,0 +1,418 @@ +out = new ConsoleOutput(); + $this->io = $this->getMockBuilder('Cake\Console\ConsoleIo')->getMock(); + $this->Users = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + + $this->Shell = $this->getMockBuilder('CakeDC\Users\Shell\UsersShell') + ->setMethods(['in', 'out', '_stop', 'clear', '_usernameSeed', '_generateRandomPassword', + '_generateRandomUsername', '_generatedHashedPassword', 'error', '_updateUser']) + ->setConstructorArgs([$this->io]) + ->getMock(); + + $this->Shell->Users = $this->getMockBuilder('CakeDC\Users\Model\Table\UsersTable') + ->setMethods(['generateUniqueUsername', 'newEntity', 'save', 'updateAll']) + ->getMock(); + + $this->Shell->Command = $this->getMockBuilder('Cake\Shell\Task\CommandTask') + ->setMethods(['in', '_stop', 'clear', 'out']) + ->setConstructorArgs([$this->io]) + ->getMock(); + } + + /** + * Tear Down + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + unset($this->Shell); + } + + /** + * Add user test + * Adding user with username, email, password and role + * + * @return void + */ + public function testAddUser() + { + $user = [ + 'username' => 'yeliparra', + 'password' => '123', + 'email' => 'yeli.parra@example.com', + 'active' => 1, + ]; + $role = 'tester'; + + $this->Shell->expects($this->never()) + ->method('_generateRandomUsername'); + + $this->Shell->expects($this->never()) + ->method('_generateRandomPassword'); + + $this->Shell->Users->expects($this->once()) + ->method('generateUniqueUsername') + ->with($user['username']) + ->will($this->returnValue($user['username'])); + + $entityUser = $this->Users->newEntity($user); + $entityUser->role = $role; + + $this->Shell->Users->expects($this->once()) + ->method('newEntity') + ->with($user) + ->will($this->returnValue($entityUser)); + + $userSaved = $entityUser; + $userSaved->id = 'my-id'; + + $this->Shell->Users->expects($this->once()) + ->method('save') + ->with($entityUser) + ->will($this->returnValue($userSaved)); + + $this->Shell->runCommand(['addUser', '--username=' . $user['username'], '--password=' . $user['password'], '--email=' . $user['email'], '--role=' . $role]); + } + + /** + * Add user test + * Adding user passing no params + * + * @return void + */ + public function testAddUserWithNoParams() + { + $user = [ + 'username' => 'anakin', + 'password' => 'mypassword', + 'email' => 'anakin@example.com', + 'active' => 1, + ]; + + $this->Shell->Users->expects($this->once()) + ->method('generateUniqueUsername') + ->with($user['username']) + ->will($this->returnValue($user['username'])); + + $this->Shell->expects($this->once()) + ->method('_generateRandomPassword') + ->will($this->returnValue($user['password'])); + + $this->Shell->expects($this->once()) + ->method('_generateRandomUsername') + ->will($this->returnValue($user['username'])); + + $entityUser = $this->Users->newEntity($user); + $entityUser->role = 'user'; + + $this->Shell->Users->expects($this->once()) + ->method('newEntity') + ->with($user) + ->will($this->returnValue($entityUser)); + + $userSaved = $entityUser; + $userSaved->id = 'my-id'; + + $this->Shell->Users->expects($this->once()) + ->method('save') + ->with($entityUser) + ->will($this->returnValue($userSaved)); + + //TODO: Add assertions with 'out' + + $this->Shell->runCommand(['addUser']); + } + + /** + * Add user test + * Adding user with username, email, password and role + * + * @return void + */ + public function testAddSuperuser() + { + $user = [ + 'username' => 'yeliparra', + 'password' => '123', + 'email' => 'yeli.parra@example.com', + 'active' => 1, + ]; + $role = 'tester'; + + $this->Shell->expects($this->never()) + ->method('_generateRandomUsername'); + + $this->Shell->expects($this->never()) + ->method('_generateRandomPassword'); + + $this->Shell->Users->expects($this->once()) + ->method('generateUniqueUsername') + ->with($user['username']) + ->will($this->returnValue($user['username'])); + + $entityUser = $this->Users->newEntity($user); + $entityUser->role = $role; + + $this->Shell->Users->expects($this->once()) + ->method('newEntity') + ->with($user) + ->will($this->returnValue($entityUser)); + + $userSaved = $entityUser; + $userSaved->id = 'my-id'; + $userSaved->is_superuser = true; + + $this->Shell->Users->expects($this->once()) + ->method('save') + ->with($entityUser) + ->will($this->returnValue($userSaved)); + + $this->Shell->runCommand(['addSuperuser', '--username=' . $user['username'], '--password=' . $user['password'], '--email=' . $user['email'], '--role=' . $role]); + } + + /** + * Add superadmin user + * + * @return void + */ + public function testAddSuperuserWithNoParams() + { + $this->Shell->Users->expects($this->once()) + ->method('generateUniqueUsername') + ->with('superadmin') + ->will($this->returnValue('superadmin')); + + $this->Shell->expects($this->once()) + ->method('_generateRandomPassword') + ->will($this->returnValue('password')); + + $user = [ + 'username' => 'superadmin', + 'password' => 'password', + 'email' => 'superadmin@example.com', + 'active' => 1, + ]; + $entityUser = $this->Users->newEntity($user); + + $this->Shell->Users->expects($this->once()) + ->method('newEntity') + ->with($user) + ->will($this->returnValue($entityUser)); + + $userSaved = $entityUser; + $userSaved->id = 'my-id'; + $userSaved->is_superuser = true; + $userSaved->role = 'superuser'; + + $this->Shell->Users->expects($this->once()) + ->method('save') + ->with($entityUser) + ->will($this->returnValue($userSaved)); + + $this->Shell->runCommand(['addSuperuser']); + } + + /** + * Reset all passwords + * + * @return void + */ + public function testResetAllPasswords() + { + $this->Shell->expects($this->once()) + ->method('_generatedHashedPassword') + ->will($this->returnValue('hashedPasssword')); + + $this->Shell->Users->expects($this->once()) + ->method('updateAll') + ->with(['password' => 'hashedPasssword'], ['id IS NOT NULL']); + + $this->Shell->runCommand(['resetAllPasswords', '123']); + } + + /** + * Reset all passwords + * + * @expectedException \Cake\Console\Exception\StopException + * @expectedExceptionMessage Please enter a password. + */ + public function testResetAllPasswordsNoPassingParams() + { + $this->Shell->runCommand(['resetAllPasswords']); + } + + /** + * Reset password + * + * @return void + */ + public function testResetPassword() + { + $user = $this->Users->newEntity(); + $user->username = 'user-1'; + $user->password = 'password'; + + $this->Shell->expects($this->once()) + ->method('_updateUser') + ->will($this->returnValue($user)); + + $this->Shell->runCommand(['resetPassword', 'user-1', 'password']); + } + + /** + * Change role + * + * @return void + */ + public function testChangeRole() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); + $this->assertSame('admin', $user['role']); + $this->Shell->runCommand(['changeRole', 'user-1', 'another-role']); + $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); + $this->assertSame('another-role', $user['role']); + } + + /** + * Activate user + * + * @return void + */ + public function testActivateUser() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); + $this->assertFalse($user['active']); + $this->Shell->runCommand(['activateUser', 'user-1']); + $user = $this->Users->get('00000000-0000-0000-0000-000000000001'); + $this->assertTrue($user['active']); + } + + /** + * Delete user + * + * @return void + * @expected + */ + public function testDeleteUser() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + + $this->assertNotEmpty($this->Users->findById('00000000-0000-0000-0000-000000000001')->first()); + $this->assertNotEmpty($this->Users->SocialAccounts->findByUserId('00000000-0000-0000-0000-000000000001')->toArray()); + $this->Shell->runCommand(['deleteUser', 'user-1']); + $this->assertEmpty($this->Users->findById('00000000-0000-0000-0000-000000000001')->first()); + $this->assertEmpty($this->Users->SocialAccounts->findByUserId('00000000-0000-0000-0000-000000000001')->toArray()); + + $this->assertNotEmpty($this->Users->findById('00000000-0000-0000-0000-000000000005')->first()); + $this->Shell->runCommand(['deleteUser', 'user-5']); + $this->assertEmpty($this->Users->findById('00000000-0000-0000-0000-000000000005')->first()); + } + + /** + * test + * + * @return void + */ + public function testAddUserCustomRole() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + $this->assertEmpty($this->Users->findByUsername('custom')->first()); + $this->Shell->runCommand([ + 'addUser', + '--username=custom', + '--password=12345678', + '--email=custom@example.com', + '--role=custom' + ]); + $user = $this->Users->findByUsername('custom')->first(); + $this->assertSame('custom', $user['role']); + } + + /** + * test + * + * @return void + */ + public function testAddUserDefaultRole() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + $this->assertEmpty($this->Users->findByUsername('custom')->first()); + Configure::write('Users.Registration.defaultRole', false); + $this->Shell->runCommand([ + 'addUser', + '--username=custom', + '--password=12345678', + '--email=custom@example.com', + ]); + $user = $this->Users->findByUsername('custom')->first(); + $this->assertSame('user', $user['role']); + } + + /** + * test + * + * @return void + */ + public function testAddUserCustomDefaultRole() + { + $this->Shell = new UsersShell($this->io); + $this->Shell->Users = $this->Users; + $this->assertEmpty($this->Users->findByUsername('custom')->first()); + Configure::write('Users.Registration.defaultRole', 'emperor'); + $this->Shell->runCommand([ + 'addUser', + '--username=custom', + '--password=12345678', + '--email=custom@example.com', + ]); + $user = $this->Users->findByUsername('custom')->first(); + $this->assertSame('emperor', $user['role']); + } +} diff --git a/tests/TestCase/Traits/RandomStringTraitTest.php b/tests/TestCase/Traits/RandomStringTraitTest.php new file mode 100644 index 000000000..f1411a44a --- /dev/null +++ b/tests/TestCase/Traits/RandomStringTraitTest.php @@ -0,0 +1,43 @@ +Trait = $this->getMockForTrait('CakeDC\Users\Traits\RandomStringTrait'); + } + + public function tearDown() + { + parent::tearDown(); + } + + public function testRandomString() + { + $result = $this->Trait->randomString(); + $this->assertEquals(10, strlen($result)); + + $result = $this->Trait->randomString(30); + $this->assertEquals(30, strlen($result)); + + $result = $this->Trait->randomString('-300'); + $this->assertEquals(10, strlen($result)); + + $result = $this->Trait->randomString('text'); + $this->assertEquals(10, strlen($result)); + } +} diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php new file mode 100644 index 000000000..3817c10ef --- /dev/null +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -0,0 +1,156 @@ +AuthLink = new AuthLinkHelper($view); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + unset($this->AuthLink); + + parent::tearDown(); + } + + /** + * Test link + * + * @return void + */ + public function testLinkFalse() + { + $link = $this->AuthLink->link('title', ['controller' => 'noaccess']); + $this->assertSame(false, $link); + } + + /** + * Test link + * + * @return void + */ + public function testLinkAuthorized() + { + $view = new View(); + $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') + ->setMethods(['dispatch']) + ->getMock(); + EventManager::instance($eventManagerMock); + $this->AuthLink = new AuthLinkHelper($view); + $result = new Event('dispatch-result'); + $result->result = true; + $eventManagerMock->expects($this->once()) + ->method('dispatch') + ->will($this->returnValue($result)); + + $link = $this->AuthLink->link('title', '/', ['before' => 'before_', 'after' => '_after', 'class' => 'link-class']); + $this->assertSame('before_title_after', $link); + } + + /** + * Test link + * + * @return void + */ + public function testLinkAuthorizedAllowedTrue() + { + $view = new View(); + $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') + ->setMethods(['dispatch']) + ->getMock(); + EventManager::instance($eventManagerMock); + $this->AuthLink = new AuthLinkHelper($view); + $result = new Event('dispatch-result'); + $result->result = true; + $eventManagerMock->expects($this->never()) + ->method('dispatch'); + + $link = $this->AuthLink->link('title', '/', ['allowed' => true, 'before' => 'before_', 'after' => '_after', 'class' => 'link-class']); + $this->assertSame('before_title_after', $link); + } + + /** + * Test link + * + * @return void + */ + public function testLinkAuthorizedAllowedFalse() + { + $view = new View(); + $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') + ->setMethods(['dispatch']) + ->getMock(); + $view->getEventManager($eventManagerMock); + $this->AuthLink = new AuthLinkHelper($view); + $result = new Event('dispatch-result'); + $eventManagerMock->expects($this->never()) + ->method('dispatch'); + $link = $this->AuthLink->link('title', '/', ['allowed' => false, 'before' => 'before_', 'after' => '_after', 'class' => 'link-class']); + $this->assertFalse($link); + } + + /** + * Test isAuthorized + * + * @return void + */ + public function testIsAuthorized() + { + $view = new View(); + $eventManagerMock = $this->getMockBuilder('Cake\Event\EventManager') + ->setMethods(['dispatch']) + ->getMock(); + EventManager::instance($eventManagerMock); + $this->AuthLink = new AuthLinkHelper($view); + $result = new Event('dispatch-result'); + $result->result = true; + $eventManagerMock->expects($this->once()) + ->method('dispatch') + ->will($this->returnValue($result)); + + $result = $this->AuthLink->isAuthorized(['controller' => 'MyController', 'action' => 'myAction']); + $this->assertTrue($result); + } +} diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php new file mode 100644 index 000000000..3fafbb9bf --- /dev/null +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -0,0 +1,380 @@ +oauthConfig === null) { + $this->oauthConfig = (array)Configure::read('OAuth'); + $this->socialLogin = Configure::read('Users.Social.login'); + } + + parent::setUp(); + $this->View = $this->getMockBuilder('Cake\View\View') + ->setMethods(['append']) + ->getMock(); + //Assuming all these url's are authorized + $this->AuthLink = $this->getMockBuilder('CakeDC\Users\View\Helper\AuthLinkHelper') + ->setMethods(['isAuthorized']) + ->setConstructorArgs([$this->View]) + ->getMock(); + $this->AuthLink->expects($this->any()) + ->method('isAuthorized') + ->will($this->returnValue(true)); + $this->User = new UserHelper($this->View); + $this->User->AuthLink = $this->AuthLink; + $this->request = new ServerRequest(); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + Configure::write('OAuth', $this->oauthConfig); + Configure::write('Users.Social.login', $this->socialLogin); + unset($this->User); + + parent::tearDown(); + } + + /** + * Test twitterLogin + * + * @return void + */ + public function testLogout() + { + $result = $this->User->logout(); + $expected = 'Logout'; + $this->assertEquals($expected, $result); + } + + /** + * Test twitterLogin + * + * @return void + */ + public function testLogoutDifferentMessage() + { + $result = $this->User->logout('Sign Out'); + $expected = 'Sign Out'; + $this->assertEquals($expected, $result); + } + + /** + * Test twitterLogin + * + * @return void + */ + public function testLogoutWithOptions() + { + $result = $this->User->logout('Sign Out', ['class' => 'logout']); + $expected = 'Sign Out'; + $this->assertEquals($expected, $result); + } + + /** + * Test link + * + * @return void + */ + public function testWelcome() + { + $session = $this->getMockBuilder('Cake\Http\Session') + ->setMethods(['read']) + ->getMock(); + $session->expects($this->at(0)) + ->method('read') + ->with('Auth.User.id') + ->will($this->returnValue(2)); + + $session->expects($this->at(1)) + ->method('read') + ->with('Auth.User.first_name') + ->will($this->returnValue('david')); + + $this->User->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['getSession']) + ->getMock(); + $this->User->request->expects($this->any()) + ->method('getSession') + ->will($this->returnValue($session)); + + $expected = 'Welcome, david'; + $result = $this->User->welcome(); + $this->assertEquals($expected, $result); + } + + /** + * Test link + * + * @return void + */ + public function testWelcomeNotLoggedInUser() + { + $session = $this->getMockBuilder('Cake\Http\Session') + ->setMethods(['read']) + ->getMock(); + $session->expects($this->at(0)) + ->method('read') + ->with('Auth.User.id') + ->will($this->returnValue(null)); + + $this->User->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['getSession']) + ->getMock(); + $this->User->request->expects($this->any()) + ->method('getSession') + ->will($this->returnValue($session)); + + $result = $this->User->welcome(); + $this->assertEmpty($result); + } + + /** + * Test add ReCaptcha field + * + * @return void + */ + public function testAddReCaptcha() + { + Configure::write('Users.reCaptcha.key', 'testKey'); + Configure::write('Users.reCaptcha.theme', 'light'); + Configure::write('Users.reCaptcha.size', 'normal'); + Configure::write('Users.reCaptcha.tabindex', '3'); + $result = $this->User->addReCaptcha(); + $this->assertEquals('
', $result); + } + + /** + * Test add ReCaptcha field + * + * @return void + */ + public function testAddReCaptchaEmpty() + { + $result = $this->User->addReCaptcha(); + $expected = '

reCaptcha is not configured! Please configure Users.reCaptcha.key

'; + $this->assertEquals($expected, $result); + } + + /** + * Test add ReCaptcha field + * + * @return void + */ + public function testAddReCaptchaScript() + { + $this->View->expects($this->at(0)) + ->method('append') + ->with('script', $this->stringContains('https://www.google.com/recaptcha/api.js')); + $this->User->addReCaptchaScript(); + } + + /** + * Test social login link + * + * @return void + */ + public function testSocialLoginLink() + { + $result = $this->User->socialLogin('facebook'); + $this->assertEquals('Sign in with Facebook', $result); + + $result = $this->User->socialLogin('twitter', ['label' => 'Register with']); + $this->assertEquals('Register with Twitter', $result); + } + + /** + * test + * + * @return void + */ + public function testSocialLoginTranslation() + { + I18n::setLocale('es_ES'); + $result = $this->User->socialLogin('facebook'); + $this->assertEquals('Iniciar sesiĆ³n con Facebook', $result); + I18n::setLocale('en_US'); + } + + /** + * Test social connect link list + * + * @return void + */ + public function testSocialConnectLinkList() + { + Configure::write('Users.Social.login', true); + + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); + Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); + + $actual = $this->User->socialConnectLinkList(); + $expected = ' Connect with Facebook'; + $expected .= ' Connect with Google'; + $this->assertEquals($expected, $actual); + } + + /** + * Test social connect link list, user is connected with facebook + * + * @return void + */ + public function testSocialConnectLinkListIsConnectedWithFacebook() + { + Configure::write('Users.Social.login', true); + + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); + Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); + + $socialAccounts = [ + new SocialAccount([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'provider' => 'Facebook', + 'username' => 'user-1-fb', + 'reference' => 'reference-1-1234', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', + 'token' => 'token-1234', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => false, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ]) + ]; + $actual = $this->User->socialConnectLinkList($socialAccounts); + $expected = ' Connected with Facebook'; + $expected .= ' Connect with Google'; + $this->assertEquals($expected, $actual); + } + + /** + * Test social connect link list, social is not enabled + * + * @return void + */ + public function testSocialConnectLinkListSocialIsNotEnabled() + { + Configure::write('Users.Social.login', false); + + Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + + Configure::write('OAuth.providers.google.options.clientId', 'testclientidgoogtestclientidgoog'); + Configure::write('OAuth.providers.google.options.clientSecret', 'testclientsecretgoogtestclientsecretgoog'); + + $socialAccounts = [ + new SocialAccount([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'provider' => 'Facebook', + 'username' => 'user-1-fb', + 'reference' => 'reference-1-1234', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', + 'token' => 'token-1234', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => false, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ]) + ]; + $actual = $this->User->socialConnectLinkList($socialAccounts); + $expected = ''; + $this->assertEquals($expected, $actual); + } + + /** + * Test social connect link list, social is enabled but any provider was configured + * + * @return void + */ + public function testSocialConnectLinkListSocialEnabledButNotConfiguredProvider() + { + Configure::write('Users.Social.login', true); + + $socialAccounts = [ + new SocialAccount([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'user_id' => '00000000-0000-0000-0000-000000000001', + 'provider' => 'Facebook', + 'username' => 'user-1-fb', + 'reference' => 'reference-1-1234', + 'avatar' => 'Lorem ipsum dolor sit amet', + 'description' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', + 'token' => 'token-1234', + 'token_secret' => 'Lorem ipsum dolor sit amet', + 'token_expires' => '2015-05-22 21:52:44', + 'active' => false, + 'data' => '', + 'created' => '2015-05-22 21:52:44', + 'modified' => '2015-05-22 21:52:44' + ]) + ]; + $actual = $this->User->socialConnectLinkList($socialAccounts); + $expected = ''; + $this->assertEquals($expected, $actual); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 000000000..e94978c62 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,130 @@ + 'Users\Test\App']); + +Cake\Core\Configure::write('debug', true); +Cake\Core\Configure::write('App.encoding', 'UTF-8'); + +ini_set('intl.default_locale', 'en_US'); + +$TMP = new \Cake\Filesystem\Folder(TMP); +$TMP->create(TMP . 'cache/models', 0777); +$TMP->create(TMP . 'cache/persistent', 0777); +$TMP->create(TMP . 'cache/views', 0777); + +$cache = [ + 'default' => [ + 'engine' => 'File', + ], + '_cake_core_' => [ + 'className' => 'File', + 'prefix' => 'users_myapp_cake_core_', + 'path' => CACHE . 'persistent/', + 'serialize' => true, + 'duration' => '+10 seconds', + ], + '_cake_model_' => [ + 'className' => 'File', + 'prefix' => 'users_app_cake_model_', + 'path' => CACHE . 'models/', + 'serialize' => 'File', + 'duration' => '+10 seconds', + ], +]; + +Cake\Cache\Cache::setConfig($cache); +Cake\Core\Configure::write('Session', [ + 'defaults' => 'php' +]); + +//init router +\Cake\Routing\Router::reload(); + +\Cake\Core\Plugin::load('CakeDC/Users', [ + 'path' => dirname(dirname(__FILE__)) . DS, + 'routes' => true +]); +if (file_exists($root . '/config/bootstrap.php')) { + require $root . '/config/bootstrap.php'; +} + +Cake\Routing\DispatcherFactory::add('Routing'); +Cake\Routing\DispatcherFactory::add('ControllerFactory'); + +class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\AppController'); + +// Ensure default test connection is defined +if (!getenv('db_dsn')) { + putenv('db_dsn=sqlite:///:memory:'); +} + +Cake\Datasource\ConnectionManager::setConfig('test', [ + 'url' => getenv('db_dsn'), +// 'className' => 'Cake\Database\Connection', +// 'driver' => 'Cake\Database\Driver\Postgres', +// 'persistent' => true, +// 'host' => 'localhost', +// 'username' => 'my_app', +// 'password' => null, +// 'database' => 'test', +// 'schema' => 'public', +// 'port' => 5432, +// 'encoding' => 'utf8', +// 'flags' => [], +// 'init' => [], + 'timezone' => 'UTC' +]); + +\Cake\Core\Configure::write('App.paths.templates', [ + APP . 'Template/', +]); diff --git a/tests/config/routes.php b/tests/config/routes.php new file mode 100644 index 000000000..911b3c38b --- /dev/null +++ b/tests/config/routes.php @@ -0,0 +1,35 @@ + '/users'], function ($routes) { + $routes->fallbacks('DashedRoute'); +}); + +$oauthPath = Configure::read('Opauth.path'); +if (is_array($oauthPath)) { + Router::scope('/auth', function ($routes) use ($oauthPath) { + $routes->connect( + '/*', + $oauthPath + ); + }); +} +Router::connect('/accounts/validate/*', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'SocialAccounts', + 'action' => 'validate' +]); +Router::connect('/profile/*', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); +Router::connect('/login', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); +Router::connect('/logout', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout']); diff --git a/webroot/empty b/webroot/empty new file mode 100644 index 000000000..e69de29bb diff --git a/webroot/img/avatar_placeholder.png b/webroot/img/avatar_placeholder.png new file mode 100644 index 0000000000000000000000000000000000000000..5a29e1a2db3f5977b3f36c5ca633d9608db66288 GIT binary patch literal 4015 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 N^UK!8wU;~-{{ee?`}F_- literal 0 HcmV?d00001