From a24feeda18e7512e3aad3da609cea980ef5c266a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= Date: Fri, 20 Apr 2018 11:13:10 +0200 Subject: [PATCH 001/685] Adding new events --- Docs/Documentation/Events.md | 95 ++++++++++--------- .../Component/UsersAuthComponent.php | 2 + src/Controller/Traits/UserValidationTrait.php | 9 ++ .../Controller/Traits/BaseTraitTest.php | 4 +- .../Traits/UserValidationTraitTest.php | 49 ++++++++++ 5 files changed, 112 insertions(+), 47 deletions(-) diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md index 13e810165..1308d0705 100644 --- a/Docs/Documentation/Events.md +++ b/Docs/Documentation/Events.md @@ -1,55 +1,60 @@ Events ====== -The events in this plugin follow these conventions ...: +The events in this plugin follow these conventions `...`: -* 'Users.Component.UsersAuth.isAuthorized' -* 'Users.Component.UsersAuth.beforeLogin' -* 'Users.Component.UsersAuth.afterLogin' -* 'Users.Component.UsersAuth.afterCookieLogin' -* 'Users.Component.UsersAuth.beforeRegister' -* 'Users.Component.UsersAuth.afterRegister' -* 'Users.Component.UsersAuth.beforeLogout' -* 'Users.Component.UsersAuth.afterLogout' +* `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'); - } +/** + * 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'); - } -``` \ No newline at end of file +/** + * 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/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index f45ef42a4..b38a78c57 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -34,6 +34,8 @@ class UsersAuthComponent extends Component const EVENT_AFTER_LOGOUT = 'Users.Component.UsersAuth.afterLogout'; const EVENT_BEFORE_SOCIAL_LOGIN_USER_CREATE = 'Users.Component.UsersAuth.beforeSocialLoginUserCreate'; const EVENT_AFTER_CHANGE_PASSWORD = 'Users.Component.UsersAuth.afterResetPassword'; + const EVENT_ON_EXPIRED_TOKEN = 'Users.Component.UsersAuth.onExpiredToken'; + const EVENT_AFTER_RESEND_TOKEN_VALIDATION = 'Users.Component.UsersAuth.afterResendTokenValidation'; /** * Initialize method, setup Auth if not already done passing the $config provided and diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 2229c7abb..90085f21d 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller\Traits; +use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\TokenExpiredException; use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotFoundException; @@ -68,6 +69,10 @@ public function validate($type = null, $token = null) } 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')); } @@ -94,6 +99,10 @@ public function resendTokenValidation() 'sendEmail' => true, 'emailTemplate' => 'CakeDC/Users.validation' ])) { + $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.' diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index a7ff42461..6cc88cc19 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -121,7 +121,7 @@ protected function _mockRequestGet($withSession = false) $methods[] = 'session'; } - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods($methods) ->getMock(); $this->Trait->request->expects($this->any()) @@ -151,7 +151,7 @@ protected function _mockFlash() */ protected function _mockRequestPost($with = 'post') { - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is', 'getData', 'allow']) ->getMock(); $this->Trait->request->expects($this->any()) diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index db475020b..3747ce850 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; +use Cake\Event\Event; use Cake\Network\Request; class UserValidationTraitTest extends BaseTraitTest @@ -84,6 +85,26 @@ public function testValidateTokenExpired() $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 * @@ -146,6 +167,34 @@ public function testResendTokenValidationHappy() $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 * From 77565e1e32884fcd561d0295a802d282980f0c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= Date: Fri, 20 Apr 2018 16:49:46 +0200 Subject: [PATCH 002/685] Fixes CakeDC/users#652 and CakeDC/users#683 --- .../Traits/PasswordManagementTrait.php | 3 +- src/Controller/Traits/UserValidationTrait.php | 2 +- src/Model/Behavior/PasswordBehavior.php | 25 +++++++++- src/Model/Behavior/RegisterBehavior.php | 21 -------- .../Model/Behavior/PasswordBehaviorTest.php | 14 +++--- .../Model/Behavior/RegisterBehaviorTest.php | 48 ------------------- 6 files changed, 34 insertions(+), 79 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 1efb3a45b..67e8c2ec4 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -126,7 +126,8 @@ public function requestResetPassword() 'expiration' => Configure::read('Users.Token.expiration'), 'checkActive' => false, 'sendEmail' => true, - 'ensureActive' => Configure::read('Users.Registration.ensureActive') + 'ensureActive' => Configure::read('Users.Registration.ensureActive'), + 'type' => 'password' ]); if ($resetUser) { $msg = __d('CakeDC/Users', 'Please check your email to continue with password reset process'); diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 2229c7abb..7f3d085d9 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -92,7 +92,7 @@ public function resendTokenValidation() 'expiration' => Configure::read('Users.Token.expiration'), 'checkActive' => true, 'sendEmail' => true, - 'emailTemplate' => 'CakeDC/Users.validation' + 'type' => 'email' ])) { $this->Flash->success(__d( 'CakeDC/Users', diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 852ca9a7f..2c08a0a1e 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -70,7 +70,14 @@ public function resetToken($reference, array $options = []) $user->updateToken($expiration); $saveResult = $this->_table->save($user); if (Hash::get($options, 'sendEmail')) { - $this->sendResetPasswordEmail($user); + switch (Hash::get($options, 'type')) { + case 'email': + $this->_sendValidationEmail($user); + break; + case 'password': + $this->_sendResetPasswordEmail($user); + break; + } } return $saveResult; @@ -82,13 +89,27 @@ public function resetToken($reference, array $options = []) * @param EntityInterface $user user * @return void */ - protected function sendResetPasswordEmail($user) + 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 * diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index fc3243a2f..6700fb9f7 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -194,27 +194,6 @@ public function getRegisterValidators($options) return $validator; } - /** - * @param EntityInterface $user User information - * @param array $options ['tokenExpiration] - * @return bool|EntityInterface - */ - public function resendValidationEmail($user, $options) - { - if ($user->active) { - throw new UserAlreadyActiveException(__d('CakeDC/Users', "User account already validated")); - } - - $tokenExpiration = Hash::get($options, 'token_expiration'); - $user = $this->_updateActive($user, true, $tokenExpiration); - $userSaved = $this->_table->saveOrFail($user); - if ($userSaved) { - $this->_sendValidationEmail($userSaved); - } - - return $userSaved; - } - /** * Wrapper for mailer * diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 5ba5a7950..d25bac7aa 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -44,7 +44,7 @@ public function setUp() parent::setUp(); $this->table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $this->Behavior = $this->getMockBuilder('CakeDC\Users\Model\Behavior\PasswordBehavior') - ->setMethods(['sendResetPasswordEmail']) + ->setMethods(['_sendResetPasswordEmail']) ->setConstructorArgs([$this->table]) ->getMock(); Email::setConfigTransport('test', [ @@ -79,7 +79,7 @@ public function testResetToken() $user = $this->table->findByUsername('user-1')->first(); $token = $user->token; $this->Behavior->expects($this->never()) - ->method('sendResetPasswordEmail') + ->method('_sendResetPasswordEmail') ->with($user); $result = $this->Behavior->resetToken('user-1', [ 'expiration' => 3600, @@ -100,11 +100,12 @@ public function testResetTokenSendEmail() $token = $user->token; $tokenExpires = $user->token_expires; $this->Behavior->expects($this->once()) - ->method('sendResetPasswordEmail'); + ->method('_sendResetPasswordEmail'); $result = $this->Behavior->resetToken('user-1', [ 'expiration' => 3600, 'checkActive' => true, - 'sendEmail' => true + 'sendEmail' => true, + 'type' => 'password' ]); $this->assertNotEquals($token, $result->token); $this->assertNotEquals($tokenExpires, $result->token_expires); @@ -158,7 +159,7 @@ public function testResetTokenUserAlreadyActive() $this->table->expects($this->never()) ->method('save'); $this->Behavior->expects($this->never()) - ->method('sendResetPasswordEmail'); + ->method('_sendResetPasswordEmail'); $this->Behavior->resetToken('user-4', [ 'expiration' => 3600, 'checkActive' => true, @@ -229,7 +230,8 @@ public function testEmailOverride() $this->Behavior->resetToken('user-1', [ 'expiration' => 3600, 'checkActive' => true, - 'sendEmail' => true + 'sendEmail' => true, + 'type' => 'password' ]); } } diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index d1dbcee6e..0dfa3ffdf 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -317,52 +317,4 @@ public function testRegisterUsingCustomRole() ]); $this->assertSame('emperor', $result['role']); } - - /** - * Test resendValidationEmail method - * - * @return void - */ - public function testResendValidationEmail() - { - $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->assertFalse($result->active); - $originalExpiration = $result->token_expires; - $updatedResult = $this->Table->resendValidationEmail($result, ['token_expiration' => 4000]); - $this->assertNotEmpty($updatedResult); - $this->assertFalse($updatedResult->active); - $newExpiration = $updatedResult->token_expires; - $this->assertNotEquals($originalExpiration, $newExpiration); - } - - /** - * Test resendValidationEmail method throw exception on active user - * - * @return void - */ - public function testResendValidationEmailThrows() - { - $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]); - $activeUser = $this->Table->activateUser($result); - $this->expectException(UserAlreadyActiveException::class); - $updatedResult = $this->Table->resendValidationEmail($activeUser, ['token_expiration' => 4000]); - } } From 2e2219b499a4e01af96eaa3b5909e68531a0203b Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 1 May 2018 13:05:36 +0200 Subject: [PATCH 003/685] Add Pinterest and Tumblr mappers. Auth is not available yet (just mappers) --- src/Auth/Social/Mapper/Pinterest.php | 24 ++++++++++++++ src/Auth/Social/Mapper/Tumblr.php | 47 ++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src/Auth/Social/Mapper/Pinterest.php create mode 100644 src/Auth/Social/Mapper/Tumblr.php 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..f5e4867ea --- /dev/null +++ b/src/Auth/Social/Mapper/Tumblr.php @@ -0,0 +1,47 @@ + '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']); + } +} From 78db7ad39f47dcb14862d1a8ac511a92913b1f29 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 May 2018 12:05:03 -0300 Subject: [PATCH 004/685] Added custom authenticators --- .../AuthenticatorFeedbackInterface.php | 17 +++ src/Authenticator/CookieAuthenticator.php | 47 +++++++ src/Authenticator/FormAuthenticator.php | 125 ++++++++++++++++++ .../GoogleTwoFactorAuthenticator.php | 82 ++++++++++++ 4 files changed, 271 insertions(+) create mode 100644 src/Authenticator/AuthenticatorFeedbackInterface.php create mode 100644 src/Authenticator/CookieAuthenticator.php create mode 100644 src/Authenticator/FormAuthenticator.php create mode 100644 src/Authenticator/GoogleTwoFactorAuthenticator.php diff --git a/src/Authenticator/AuthenticatorFeedbackInterface.php b/src/Authenticator/AuthenticatorFeedbackInterface.php new file mode 100644 index 000000000..54a441f1e --- /dev/null +++ b/src/Authenticator/AuthenticatorFeedbackInterface.php @@ -0,0 +1,17 @@ +getConfig('rememberMeField'); + + $bodyData = $request->getParsedBody(); + if (empty($bodyData)) { + $session = $request->getAttribute('session'); + $bodyData = $session->read('CookieAuth'); + $session->delete('CookieAuth'); + } + + if (!$this->_checkUrl($request) || !is_array($bodyData) || empty($bodyData[$field])) { + return [ + 'request' => $request, + 'response' => $response + ]; + } + + $value = $this->_createToken($identity); + $cookie = $this->_createCookie($value); + + return [ + 'request' => $request, + 'response' => $response->withAddedHeader('Set-Cookie', $cookie->toHeaderValue()) + ]; + } +} diff --git a/src/Authenticator/FormAuthenticator.php b/src/Authenticator/FormAuthenticator.php new file mode 100644 index 000000000..bf02b0308 --- /dev/null +++ b/src/Authenticator/FormAuthenticator.php @@ -0,0 +1,125 @@ +identifier = $identifier; + $this->config = $config; + } + + /** + * Gets the actual base authenticator + * + * @return \Authentication\Authenticator\FormAuthenticator + */ + protected function getBaseAuthenticator() + { + if ($this->baseAuthenticator === null) { + $this->baseAuthenticator = $this->createBaseAuthenticator($this->identifier, $this->config); + } + + return $this->baseAuthenticator; + } + + /** + * Create the base authenticator + * + * @param \Authentication\Identifier\IdentifierInterface $identifier Identifier or identifiers collection. + * @param array $config Configuration settings. + * + * @return \Authentication\Authenticator\FormAuthenticator + */ + protected function createBaseAuthenticator(IdentifierInterface $identifier, array $config = []) + { + return new BaseFormAuthenticator($identifier, $config); + } + + /** + * Get the last result of authenticator + * + * @return Result|null + */ + public function getLastResult() + { + return $this->lastResult; + } + + /** + * Authenticates the identity contained in a request. Wrapper for Authentication\Authenticator\FormAuthenticator + * to also check reCaptcha. Will use the `config.userModel`, and `config.fields` + * to find POST data that is used to find a matching record in the `config.userModel`. Will return false if + * there is no post data, either username or password is missing, or if the scope conditions have not been met. + * + * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. + * @param \Psr\Http\Message\ResponseInterface $response Unused response object. + * @return \Authentication\Authenticator\ResultInterface + */ + public function authenticate(ServerRequestInterface $request, ResponseInterface $response) + { + $result = $this->getBaseAuthenticator()->authenticate($request, $response); + if (!Configure::read('Users.reCaptcha.login') || in_array($result->getStatus(), [Result::FAILURE_OTHER, Result::FAILURE_CREDENTIALS_MISSING])) { + return $this->lastResult = $result; + } + + $data = $request->getParsedBody(); + $captcha = $data['g-recaptcha-response'] ? $data['g-recaptcha-response'] : null; + + $valid = $this->validateReCaptcha( + $captcha, + $request->clientIp() + ); + + if ($valid) { + return $this->lastResult = $result; + } + + return $this->lastResult = new Result(null, self::FAILURE_INVALID_RECAPTCHA); + } +} \ No newline at end of file diff --git a/src/Authenticator/GoogleTwoFactorAuthenticator.php b/src/Authenticator/GoogleTwoFactorAuthenticator.php new file mode 100644 index 000000000..72ca6aa05 --- /dev/null +++ b/src/Authenticator/GoogleTwoFactorAuthenticator.php @@ -0,0 +1,82 @@ + null, + 'urlChecker' => 'Authentication.Default', + ]; + + + /** + * Prepares the error object for a login URL error + * + * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. + * @return \Authentication\Authenticator\ResultInterface + */ + protected function _buildLoginUrlErrorResult($request) + { + $errors = [ + sprintf( + 'Login URL `%s` did not match `%s`.', + (string)$request->getUri(), + implode('` or `', (array)$this->getConfig('loginUrl')) + ) + ]; + + return new Result(null, Result::FAILURE_OTHER, $errors); + } + + /** + * Authenticates the identity contained in a request. Will use the `config.userModel`, and `config.fields` + * to find POST data that is used to find a matching record in the `config.userModel`. Will return false if + * there is no post data, either username or password is missing, or if the scope conditions have not been met. + * + * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. + * @param \Psr\Http\Message\ResponseInterface $response Unused response object. + * @return \Authentication\Authenticator\ResultInterface + */ + public function authenticate(ServerRequestInterface $request, ResponseInterface $response) + { + if (!$this->_checkUrl($request)) { + return $this->_buildLoginUrlErrorResult($request); + } + + $data = $request->getSession()->read('GoogleTwoFactor.User'); + + if ($data === null) { + return new Result(null, Result::FAILURE_CREDENTIALS_MISSING, [ + 'Login credentials not found' + ]); + } + + $request->getSession()->delete('GoogleTwoFactor.User'); + + return new Result($data, Result::SUCCESS); + } +} From 20b5d67f81dc3f3b4dff6ec03c1e8f9428a141bc Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 May 2018 12:06:16 -0300 Subject: [PATCH 005/685] Added Social Layer --- src/Social/Locator/DatabaseLocator.php | 111 +++++ src/Social/Locator/LocatorInterface.php | 17 + src/Social/ProviderConfig.php | 132 ++++++ src/Social/Service/OAuth1Service.php | 104 +++++ src/Social/Service/OAuth2Service.php | 116 +++++ src/Social/Service/OAuthServiceAbstract.php | 34 ++ src/Social/Service/ServiceFactory.php | 60 +++ src/Social/Service/ServiceInterface.php | 58 +++ .../Social/Locator/DatabaseLocatorTest.php | 171 ++++++++ tests/TestCase/Social/ProviderConfigTest.php | 293 +++++++++++++ .../Social/Service/OAuth1ServiceTest.php | 364 ++++++++++++++++ .../Social/Service/OAuth2ServiceTest.php | 395 ++++++++++++++++++ .../Social/Service/ServiceFactoryTest.php | 250 +++++++++++ 13 files changed, 2105 insertions(+) create mode 100644 src/Social/Locator/DatabaseLocator.php create mode 100644 src/Social/Locator/LocatorInterface.php create mode 100644 src/Social/ProviderConfig.php create mode 100644 src/Social/Service/OAuth1Service.php create mode 100644 src/Social/Service/OAuth2Service.php create mode 100644 src/Social/Service/OAuthServiceAbstract.php create mode 100644 src/Social/Service/ServiceFactory.php create mode 100644 src/Social/Service/ServiceInterface.php create mode 100644 tests/TestCase/Social/Locator/DatabaseLocatorTest.php create mode 100644 tests/TestCase/Social/ProviderConfigTest.php create mode 100644 tests/TestCase/Social/Service/OAuth1ServiceTest.php create mode 100644 tests/TestCase/Social/Service/OAuth2ServiceTest.php create mode 100644 tests/TestCase/Social/Service/ServiceFactoryTest.php diff --git a/src/Social/Locator/DatabaseLocator.php b/src/Social/Locator/DatabaseLocator.php new file mode 100644 index 000000000..c811bf344 --- /dev/null +++ b/src/Social/Locator/DatabaseLocator.php @@ -0,0 +1,111 @@ + 'all', + ]; + + /** + * DatabaseLocator constructor. + * + * @param array $config + */ + public function __construct(array $config = []) + { + $config += ['userModel' => Configure::read('Users.table')]; + $this->setConfig($config); + } + + /** + * Get or create the user based on the $rawData + * + * @param array $rawData mapped social user data + * @return User + */ + public function getOrCreate(array $rawData): User + { + if (!$this->getConfig('userModel')) { + throw new InvalidSettingsException(__d('CakeDC/Users', 'Users table is not defined')); + } + + $user = $this->_socialLogin($rawData); + + if (!$user) { + throw new RecordNotFoundException(__d('CakeDC/Users', 'Could not locate user')); + } + // If new SocialAccount was created $user is returned containing it + if ($user->get('social_accounts')) { + $this->dispatchEvent(AuthListener::EVENT_AFTER_SOCIAL_REGISTER, compact('user')); + } + + $user = $this->findUser($user)->firstOrFail(); + + return $user; + } + + /** + * Get query object for fetching user from database. + * + * @param User $user The user. + * + * @return \Cake\Orm\Query + */ + protected function findUser($user) + { + $userModel = $this->getConfig('userModel'); + $table = TableRegistry::get($userModel); + $finder = $this->getConfig('finder'); + + $primaryKey = (array)$table->getPrimaryKey(); + + $conditions = []; + foreach ($primaryKey as $key) { + $conditions[$table->aliasField($key)] = $user->get($key); + } + + return $table->find($finder)->where($conditions); + } + + /** + * @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::get($userModel); + $user = $User->socialLogin($data, $options); + + return $user; + } + +} \ No newline at end of file diff --git a/src/Social/Locator/LocatorInterface.php b/src/Social/Locator/LocatorInterface.php new file mode 100644 index 000000000..cf498a2e9 --- /dev/null +++ b/src/Social/Locator/LocatorInterface.php @@ -0,0 +1,17 @@ + $options) { + if ($this->_isProviderEnabled($options)) { + $providers[$provider] = $options; + } + } + $oauthConfig['providers'] = $providers; + + $this->providers = $this->normalizeConfig(Hash::merge($config, $oauthConfig))['providers']; + + } + + /** + * Normalizes providers' configuration. + * + * @param array $config Array of config to normalize. + * @return array + * @throws \Exception + */ + public function normalizeConfig(array $config) + { + 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, + 'service' => null, + 'mapper' => null, + 'options' => [], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + ] + $parent; + + $config = array_intersect_key($config, $defaults); + $config += $defaults; + + array_walk($config, [$this, '_validateConfig']); + + foreach (['options', 'collaborators', 'signature'] 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 (in_array($key, ['className', 'service', 'mapper'], true) && !is_object($value) && !class_exists($value)) { + throw new InvalidProviderException([$value]); + } elseif (!is_array($value) && in_array($key, ['options', 'collaborators'])) { + throw new InvalidSettingsException([$key]); + } + } + + /** + * Returns when a provider has been enabled. + * + * @param array $options array of options by provider + * @return bool + */ + public function _isProviderEnabled($options) + { + return !empty($options['options']['redirectUri']) && !empty($options['options']['clientId']) && + !empty($options['options']['clientSecret']); + } + + /** + * Get provider config + * + * @param string $alias for provider + * @return array + */ + public function getConfig($alias): array + { + return Hash::get($this->providers, $alias, []); + } + +} \ No newline at end of file diff --git a/src/Social/Service/OAuth1Service.php b/src/Social/Service/OAuth1Service.php new file mode 100644 index 000000000..b49cf5345 --- /dev/null +++ b/src/Social/Service/OAuth1Service.php @@ -0,0 +1,104 @@ + 'clientId', + 'secret' => 'clientSecret', + 'callback_uri' => 'redirectUri' + ]; + + foreach ($map as $to => $from) { + if (array_key_exists($from, $providerConfig['options'])) { + $providerConfig['options'][$to] = $providerConfig['options'][$from]; + unset($providerConfig['options'][$from]); + } + } + $providerConfig += ['signature' => null]; + $this->setProvider($providerConfig); + $this->setConfig($providerConfig); + } + + /** + * Check if we are at getUserStep, meaning, we received a callback from provider. + * + * @param \Cake\Http\ServerRequest $request Request object. + * @return bool + */ + public function isGetUserStep(ServerRequest $request): bool + { + $oauthToken = $request->getQuery('oauth_token'); + $oauthVerifier = $request->getQuery('oauth_verifier'); + + return !empty($oauthToken) && !empty($oauthVerifier); + } + + /** + * Get a authentication url for user + * + * @param \Cake\Http\ServerRequest $request Request object. + * @return string + */ + public function getAuthorizationUrl(ServerRequest $request) + { + $temporaryCredentials = $this->provider->getTemporaryCredentials(); + $request->getSession()->write('temporary_credentials', $temporaryCredentials); + + return $this->provider->getAuthorizationUrl($temporaryCredentials); + } + + /** + * Get a user in social provider + * + * @param \Cake\Http\ServerRequest $request Request object. + * @return array + */ + public function getUser(ServerRequest $request): array + { + $oauthToken = $request->getQuery('oauth_token'); + $oauthVerifier = $request->getQuery('oauth_verifier'); + + $temporaryCredentials = $request->getSession()->read('temporary_credentials'); + $tokenCredentials = $this->provider->getTokenCredentials($temporaryCredentials, $oauthToken, $oauthVerifier); + $user = (array)$this->provider->getUserDetails($tokenCredentials); + $user['token'] = [ + 'accessToken' => $tokenCredentials->getIdentifier(), + 'tokenSecret' => $tokenCredentials->getSecret(), + ]; + + return $user; + } + + /** + * Instantiates provider object. + * + * @param array $config for provider. + * @return void + */ + protected function setProvider($config) + { + if (is_object($config['className']) && $config['className'] instanceof Server) { + $this->provider = $config['className']; + } else { + $class = $config['className']; + + $this->provider = new $class($config['options'], $config['signature']); + } + } +} diff --git a/src/Social/Service/OAuth2Service.php b/src/Social/Service/OAuth2Service.php new file mode 100644 index 000000000..6678d9967 --- /dev/null +++ b/src/Social/Service/OAuth2Service.php @@ -0,0 +1,116 @@ +setProvider($providerConfig); + $this->setConfig($providerConfig); + } + + /** + * Check if we are at getUserStep, meaning, we received a callback from provider. + * Return true when querystring code is not empty + * + * @param \Cake\Http\ServerRequest $request Request object. + * @return bool + */ + public function isGetUserStep(ServerRequest $request): bool + { + return !empty($request->getQuery('code')); + } + + /** + * Get a authentication url for user + * + * @param \Cake\Http\ServerRequest $request Request object. + * @return string + */ + public function getAuthorizationUrl(ServerRequest $request) + { + if ($this->getConfig('options.state')) { + $request->getSession()->write('oauth2state', $this->provider->getState()); + } + + return $this->provider->getAuthorizationUrl(); + } + + /** + * Get a user in social provider + * + * @param \Cake\Http\ServerRequest $request Request object. + * + * @throws BadRequestException when oauth2 state is invalid + * @return array + */ + public function getUser(ServerRequest $request): array + { + if (!$this->validate($request)) { + throw new BadRequestException('Invalid OAuth2 state'); + } + + $code = $request->getQuery('code'); + $token = $this->provider->getAccessToken('authorization_code', compact('code')); + + return compact('token') + $this->provider->getResourceOwner($token)->toArray(); + } + + /** + * Validates OAuth2 request. + * + * @param \Cake\Http\ServerRequest $request Request object. + * @return bool + */ + protected function validate(ServerRequest $request) + { + if (!array_key_exists('code', $request->getQueryParams())) { + 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; + } + + + /** + * Instantiates provider object. + * + * @param array $config for provider. + * @return void + */ + protected function setProvider($config) + { + if (is_object($config['className']) && $config['className'] instanceof AbstractProvider) { + $this->provider = $config['className']; + } else { + $class = $config['className']; + + $this->provider = new $class($config['options'], $config['collaborators']); + } + } +} \ No newline at end of file diff --git a/src/Social/Service/OAuthServiceAbstract.php b/src/Social/Service/OAuthServiceAbstract.php new file mode 100644 index 000000000..e0545dcab --- /dev/null +++ b/src/Social/Service/OAuthServiceAbstract.php @@ -0,0 +1,34 @@ +providerName; + } + + /** + * @param string $providerName + */ + public function setProviderName(string $providerName) + { + $this->providerName = $providerName; + } + +} \ No newline at end of file diff --git a/src/Social/Service/ServiceFactory.php b/src/Social/Service/ServiceFactory.php new file mode 100644 index 000000000..12f553100 --- /dev/null +++ b/src/Social/Service/ServiceFactory.php @@ -0,0 +1,60 @@ +redirectUriField = $redirectUriField; + + return $this; + } + + /** + * Create a new service based on provider alias + * + * @param string $provider provider alias + * + * @return ServiceInterface + */ + public function createFromProvider($provider): ServiceInterface + { + $config = (new ProviderConfig())->getConfig($provider); + + if (!$provider || !$config) { + throw new NotFoundException('Provider not found'); + } + + $config['options']['redirectUri'] = $config['options'][$this->redirectUriField]; + unset($config['options']['linkSocialUri'], $config['options']['callbackLinkSocialUri']); + $service = new $config['service']($config); + $service->setProviderName($provider); + + return $service; + } + + /** + * Create a new service based on request + * + * @param ServerRequest $request in use + * + * @return ServiceInterface + */ + public function createFromRequest(ServerRequest $request): ServiceInterface + { + return $this->createFromProvider($request->getAttribute('params')['provider'] ?? null); + } +} \ No newline at end of file diff --git a/src/Social/Service/ServiceInterface.php b/src/Social/Service/ServiceInterface.php new file mode 100644 index 000000000..a73489fb5 --- /dev/null +++ b/src/Social/Service/ServiceInterface.php @@ -0,0 +1,58 @@ + 'test-token', + 'expires' => 1490988496 + ]); + + $data = [ + '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' + ]; + + $user = (new Facebook($data))(); + $user['provider'] = 'facebook'; + + $this->Locator = new DatabaseLocator(); + $result = $this->Locator->getOrCreate($user); + $this->assertInstanceOf('CakeDC\Users\Model\Entity\User', $result); + $this->assertNotEmpty($result->id); + $this->assertEquals('test@gmail.com', $result->email); + $this->assertEquals('test', $result->username); + } + + /** + * Test getOrCreate method error in social login + * + * @return void + */ + public function testGetOrCreateErrorSocialLogin() + { + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + $this->Locator = $this->getMockBuilder(DatabaseLocator::class)->setMethods([ + '_socialLogin' + ])->getMock(); + $this->Locator->expects($this->once()) + ->method('_socialLogin') + ->will($this->returnValue(false)); + + $data = [ + 'token' => $Token, + 'id' => '1', + 'name' => '', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@gmail.com', + 'hometown' => [ + 'id' => '108226049197930', + 'name' => 'Madrid' + ], + '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' + ]; + + $user = (new Facebook($data))(); + $user['provider'] = 'facebook'; + + $this->expectException(RecordNotFoundException::class); + $this->Locator->getOrCreate($user); + } + + /** + * Test getOrCreate method invalid user model + * + * @return void + */ + public function testGetOrCreateInvalidUserModel() + { + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $data = [ + 'token' => $Token, + 'id' => '1', + 'name' => '', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@gmail.com', + 'hometown' => [ + 'id' => '108226049197930', + 'name' => 'Madrid' + ], + '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' + ]; + + $this->Locator = new DatabaseLocator([ + 'userModel' => false + ]); + $user = (new Facebook($data))(); + $user['provider'] = 'facebook'; + + $this->expectException(InvalidSettingsException::class); + $this->Locator->getOrCreate($user); + + } +} diff --git a/tests/TestCase/Social/ProviderConfigTest.php b/tests/TestCase/Social/ProviderConfigTest.php new file mode 100644 index 000000000..a0a8e5c8e --- /dev/null +++ b/tests/TestCase/Social/ProviderConfigTest.php @@ -0,0 +1,293 @@ +expectException(InvalidProviderException::class); + new ProviderConfig(); + } + + /** + * Test with invalid service class + * + * @return void + */ + public function testWithInvalidServiceClass() + { + Configure::write('OAuth.providers.facebook.options.clientId', '10003030300303'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'secretpassword'); + Configure::write('OAuth.providers.facebook.service', 'CakeDC\Users\Social\Service\InvalidOAuth2Service'); + + $this->expectException(InvalidProviderException::class); + new ProviderConfig(); + } + + /** + * Test with invalid mapper class + * + * @return void + */ + public function testWithInvalidMapperClass() + { + Configure::write('OAuth.providers.facebook.options.clientId', '10003030300303'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'secretpassword'); + Configure::write('OAuth.providers.facebook.mapper', 'CakeDC\Users\Auth\Social\Mapper\InvalidFacebook'); + + $this->expectException(InvalidProviderException::class); + new ProviderConfig(); + } + + /** + * Test with invalid settings options value type + * + * @return void + */ + public function testWithInvalidOptionsValueType() + { + $this->expectException(InvalidSettingsException::class); + $config = [ + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ], + 'providers' => [ + 'facebook' => [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => 'invalid options' + ], + ] + ]; + (new ProviderConfig())->normalizeConfig($config); + } + + /** + * Test with invalid settings collaborators value type + * + * @return void + */ + public function testWithInvalidCollaboratorsValueType() + { + Configure::write('OAuth.providers.facebook.options.clientId', '10003030300303'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'secretpassword'); + Configure::write('OAuth.providers.facebook.collaborators', 'johndoe'); + + $this->expectException(InvalidSettingsException::class); + new ProviderConfig(); + } + + /** + * Test with custom config + * + * @return void + */ + public function testWithCustomConfig() + { + Configure::write('OAuth.providers.facebook.options.clientId', '10003030300303'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'secretpassword'); + Configure::write('OAuth.providers.twitter.options.clientId', '20003030300303'); + Configure::write('OAuth.providers.twitter.options.clientSecret', 'weakpassword'); + Configure::write('OAuth.providers.amazon.options.clientId', '3003030300303'); + Configure::write('OAuth.providers.amazon.options.clientSecret', 'weaksecretpassword'); + + $Config = new ProviderConfig([ + 'options' => [ + 'customOption' => 'hello' + ], + ]); + $expected = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => [ + 'customOption' => 'hello', + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + $actual = $Config->getConfig('facebook'); + $this->assertEquals($expected, $actual); + } + + /** + * Test with providers enabled + * + * @return void + */ + public function testWithProvidersEnabled() + { + Configure::write('OAuth.providers.facebook.options.clientId', '10003030300303'); + Configure::write('OAuth.providers.facebook.options.clientSecret', 'secretpassword'); + Configure::write('OAuth.providers.twitter.options.clientId', '20003030300303'); + Configure::write('OAuth.providers.twitter.options.clientSecret', 'weakpassword'); + Configure::write('OAuth.providers.amazon.options.clientId', '3003030300303'); + Configure::write('OAuth.providers.amazon.options.clientSecret', 'weaksecretpassword'); + + $Config = new ProviderConfig(); + $expected = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + $actual = $Config->getConfig('facebook'); + + $this->assertEquals($expected, $actual); + + $expected = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', + 'className' => 'League\OAuth1\Client\Server\Twitter', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Twitter', + 'options' => [ + 'redirectUri' => '/auth/twitter', + 'linkSocialUri' => '/link-social/twitter', + 'callbackLinkSocialUri' => '/callback-link-social/twitter', + 'clientId' => '20003030300303', + 'clientSecret' => 'weakpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + $actual = $Config->getConfig('twitter'); + $this->assertEquals($expected, $actual); + + $expected = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => 'Luchianenco\OAuth2\Client\Provider\Amazon', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Amazon', + 'options' => [ + 'redirectUri' => '/auth/amazon', + 'linkSocialUri' => '/link-social/amazon', + 'callbackLinkSocialUri' => '/callback-link-social/amazon', + 'clientId' => '3003030300303', + 'clientSecret' => 'weaksecretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + $actual = $Config->getConfig('amazon'); + $this->assertEquals($expected, $actual); + + $expected = []; + $actual = $Config->getConfig('linkedIn'); + $this->assertEquals($expected, $actual); + + $expected = []; + $actual = $Config->getConfig('instagram'); + $this->assertEquals($expected, $actual); + + $expected = []; + $actual = $Config->getConfig('google'); + $this->assertEquals($expected, $actual); + } + + /** + * Test without providers enabled + * + * @return void + */ + public function testWithoutProvidersEnabled() + { + $Config = new ProviderConfig(); + $expected = []; + $actual = $Config->getConfig('facebook'); + $this->assertEquals($expected, $actual); + + $expected = []; + $actual = $Config->getConfig('twitter'); + $this->assertEquals($expected, $actual); + + $expected = []; + $actual = $Config->getConfig('amazon'); + $this->assertEquals($expected, $actual); + + $expected = []; + $actual = $Config->getConfig('linkedIn'); + $this->assertEquals($expected, $actual); + + $expected = []; + $actual = $Config->getConfig('instagram'); + $this->assertEquals($expected, $actual); + + $expected = []; + $actual = $Config->getConfig('google'); + $this->assertEquals($expected, $actual); + } +} \ No newline at end of file diff --git a/tests/TestCase/Social/Service/OAuth1ServiceTest.php b/tests/TestCase/Social/Service/OAuth1ServiceTest.php new file mode 100644 index 000000000..1ef376069 --- /dev/null +++ b/tests/TestCase/Social/Service/OAuth1ServiceTest.php @@ -0,0 +1,364 @@ +Provider = $this->getMockBuilder('\League\OAuth1\Client\Server\Twitter')->setConstructorArgs([ + [ + 'redirectUri' => '/auth/twitter', + 'linkSocialUri' => '/link-social/twitter', + 'callback_uri' => '/callback-link-social/twitter', + 'identifier' => '20003030300303', + 'secret' => 'weakpassword','identifier' => 'clientId', + ], + ])->setMethods([ + 'getTemporaryCredentials', 'getAuthorizationUrl', 'getTokenCredentials', 'getUserDetails' + ])->getMock(); + + $config = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', + 'className' => $this->Provider, + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Twitter', + 'options' => [], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + + $this->Service = new OAuth1Service($config); + + $this->Request = ServerRequestFactory::fromGlobals(); + } + + /** + * teardown any static object changes and restore them. + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + + unset($this->Provider, $this->Service, $this->Request); + } + + /** + * Test construct + * + * @return void + */ + public function testConstruct() + { + + $service = new OAuth1Service([ + 'className' => 'League\OAuth1\Client\Server\Twitter', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Twitter', + 'options' => [ + 'redirectUri' => '/auth/twitter', + 'linkSocialUri' => '/link-social/twitter', + 'callbackLinkSocialUri' => '/callback-link-social/twitter', + 'clientId' => '20003030300303', + 'clientSecret' => 'weakpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]); + $this->assertInstanceOf(ServiceInterface::class, $service); + } + + /** + * Test getAuthorizationUrl + * + * @return void + */ + public function testGetAuthorizationUrl() + { + $Credentials = new TemporaryCredentials(); + $Credentials->setIdentifier('404405646989097789546879'); + $Credentials->setSecret('secretpasword'); + + $this->Provider->expects($this->at(0)) + ->method('getTemporaryCredentials') + ->will($this->returnValue($Credentials)); + + $this->Provider->expects($this->at(1)) + ->method('getAuthorizationUrl') + ->with( + $this->equalTo($Credentials) + ) + ->will($this->returnValue('http://twitter.com/redirect/url')); + + $actual = $this->Service->getAuthorizationUrl($this->Request); + $expected = 'http://twitter.com/redirect/url'; + $this->assertEquals($expected, $actual); + + $expected = $Credentials; + $actual = $this->Request->getSession()->read('temporary_credentials'); + $this->assertEquals($expected, $actual); + } + + /** + * Test isGetUserStep, should return true + * + * @return void + */ + public function testIsGetUserStep() + { + $uri = new Uri('/login'); + + $sessionConfig = (array)Configure::read('Session') + [ + 'defaults' => 'php', + ]; + $session = Session::create($sessionConfig); + $this->Request = new ServerRequest([ + 'uri' => $uri, + 'session' => $session, + ]); + $this->Request = $this->Request->withQueryParams([ + 'oauth_token' => 'dfio39972j3092304230', + 'oauth_verifier' => '21312h2312390839012', + ]); + + $result = $this->Service->isGetUserStep($this->Request); + $this->assertTrue($result); + } + + /** + * Test isGetUserStep, when values are empty + * + * @return void + */ + public function testIsGetUserStepWhenAllEmpty() + { + $uri = new Uri('/login'); + + $sessionConfig = (array)Configure::read('Session') + [ + 'defaults' => 'php', + ]; + $session = Session::create($sessionConfig); + $this->Request = new ServerRequest([ + 'uri' => $uri, + 'session' => $session, + ]); + $this->Request = $this->Request->withQueryParams([ + 'oauth_token' => '', + 'oauth_verifier' => '', + ]); + + $result = $this->Service->isGetUserStep($this->Request); + $this->assertFalse($result); + + } + + /** + * Test isGetUserStep, when oauth_token value is empty + * + * @return void + */ + public function testIsGetUserStepWhenOauthTokenEmpty() + { + + $uri = new Uri('/login'); + + $sessionConfig = (array)Configure::read('Session') + [ + 'defaults' => 'php', + ]; + $session = Session::create($sessionConfig); + $this->Request = new ServerRequest([ + 'uri' => $uri, + 'session' => $session, + ]); + $this->Request = $this->Request->withQueryParams([ + 'oauth_token' => '', + 'oauth_verifier' => '21312h2312390839012', + ]); + + $result = $this->Service->isGetUserStep($this->Request); + $this->assertFalse($result); + } + + /** + * Test isGetUserStep, when oauth_verifier value is empty + * + * @return void + */ + public function testIsGetUserStepWhenOauthVerifierEmpty() + { + + $uri = new Uri('/login'); + + $sessionConfig = (array)Configure::read('Session') + [ + 'defaults' => 'php', + ]; + $session = Session::create($sessionConfig); + $this->Request = new ServerRequest([ + 'uri' => $uri, + 'session' => $session, + ]); + $this->Request = $this->Request->withQueryParams([ + 'oauth_token' => 'dfio39972j3092304230', + 'oauth_verifier' => '', + ]); + + $result = $this->Service->isGetUserStep($this->Request); + $this->assertFalse($result); + } + + /** + * Test isGetUserStep, when keys not present + * + * @return void + */ + public function testIsGetUserStepWhenOauthKeysNotPresent() + { + + $uri = new Uri('/login'); + + $sessionConfig = (array)Configure::read('Session') + [ + 'defaults' => 'php', + ]; + $session = Session::create($sessionConfig); + $this->Request = new ServerRequest([ + 'uri' => $uri, + 'session' => $session, + ]); + + + $result = $this->Service->isGetUserStep($this->Request); + $this->assertFalse($result); + } + + /** + * Test getUser method + * + * @return void + */ + public function testGetUser() + { + $this->Request = $this->Request->withQueryParams([ + 'oauth_token' => 'good39972j3092304230', + 'oauth_verifier' => '77312h2312390839012', + ]); + + $Credentials = new TemporaryCredentials(); + $Credentials->setIdentifier('404405646989097789546879'); + $Credentials->setSecret('secretpasword'); + $this->Request->getSession()->write('temporary_credentials', $Credentials); + + $TokenCredentials = new TokenCredentials(); + $TokenCredentials->setSecret('tokensecretpasswordnew'); + $TokenCredentials->setIdentifier('50589595670964649809890'); + + $user = new User(); + + $user->uid = '5698297389-2332-89879'; + $user->nickname = 'rmarcelo'; + $user->name = 'Marcelo'; + $user->location = 'Brazil'; + $user->description = 'Developer'; + $user->imageUrl = null; + $user->email = 'example@example.com'; + + $this->Provider->expects($this->never()) + ->method('getTemporaryCredentials'); + + $this->Provider->expects($this->at(0)) + ->method('getTokenCredentials') + ->with( + $this->equalTo($Credentials), + $this->equalTo('good39972j3092304230'), + $this->equalTo('77312h2312390839012') + ) + ->will($this->returnValue($TokenCredentials)); + + $this->Provider->expects($this->at(1)) + ->method('getUserDetails') + ->with( + $this->equalTo($TokenCredentials) + ) + ->will($this->returnValue($user)); + + $actual = $this->Service->getUser($this->Request); + + $expected = [ + 'uid' => '5698297389-2332-89879', + 'nickname' => 'rmarcelo', + 'name' => 'Marcelo', + 'firstName' => null, + 'lastName' => null, + 'email' => 'example@example.com', + 'location' => 'Brazil', + 'description' => 'Developer', + 'imageUrl' => null, + 'urls' => [], + 'extra' => [], + 'token' => [ + 'accessToken' => '50589595670964649809890', + 'tokenSecret' => 'tokensecretpasswordnew' + ] + ]; + $this->assertEquals($expected, $actual); + } +} diff --git a/tests/TestCase/Social/Service/OAuth2ServiceTest.php b/tests/TestCase/Social/Service/OAuth2ServiceTest.php new file mode 100644 index 000000000..eeda7b3bf --- /dev/null +++ b/tests/TestCase/Social/Service/OAuth2ServiceTest.php @@ -0,0 +1,395 @@ +Provider = $this->getMockBuilder('\League\OAuth2\Client\Provider\Facebook')->setConstructorArgs([ + [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + [] + ])->setMethods([ + 'getAccessToken', 'getState', 'getAuthorizationUrl', 'getResourceOwner' + ])->getMock(); + + $config = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => $this->Provider, + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => [ + 'state' => '__TEST_STATE__' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + + $this->Service = new OAuth2Service($config); + + $this->Request = ServerRequestFactory::fromGlobals(); + } + + /** + * teardown any static object changes and restore them. + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + + unset($this->Provider, $this->Service, $this->Request); + } + + /** + * Test construct + * + * @return void + */ + public function testConstruct() + { + + $service = new OAuth2Service([ + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => [ + 'customOption' => 'hello', + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]); + $this->assertInstanceOf(ServiceInterface::class, $service); + } + + /** + * Test isGetUserStep, should return true + * + * @return void + */ + public function testIsGetUserStep() + { + $uri = new Uri('/login'); + + $sessionConfig = (array)Configure::read('Session') + [ + 'defaults' => 'php', + ]; + $session = Session::create($sessionConfig); + $this->Request = new ServerRequest([ + 'uri' => $uri, + 'session' => $session, + ]); + $this->Request = $this->Request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + ]); + + $result = $this->Service->isGetUserStep($this->Request); + $this->assertTrue($result); + } + + /** + * Test isGetUserStep, when values is empty + * + * @return void + */ + public function testIsGetUserStepWhenEmpty() + { + $uri = new Uri('/login'); + + $sessionConfig = (array)Configure::read('Session') + [ + 'defaults' => 'php', + ]; + $session = Session::create($sessionConfig); + $this->Request = new ServerRequest([ + 'uri' => $uri, + 'session' => $session, + ]); + $this->Request = $this->Request->withQueryParams([ + 'code' => '', + ]); + + $result = $this->Service->isGetUserStep($this->Request); + $this->assertFalse($result); + + } + + /** + * Test isGetUserStep, when values is not provided + * + * @return void + */ + public function testIsGetUserStepWhenNotProvided() + { + $uri = new Uri('/login'); + + $sessionConfig = (array)Configure::read('Session') + [ + 'defaults' => 'php', + ]; + $session = Session::create($sessionConfig); + $this->Request = new ServerRequest([ + 'uri' => $uri, + 'session' => $session, + ]); + + $result = $this->Service->isGetUserStep($this->Request); + $this->assertFalse($result); + + } + + /** + * Test getAuthorizationUrl method + * + * @return void + */ + public function testGetAuthorizationUrl() + { + $this->Provider->expects($this->at(0)) + ->method('getState') + ->will($this->returnValue('_NEW_STATE_')); + + $this->Provider->expects($this->at(1)) + ->method('getAuthorizationUrl') + ->will($this->returnValue('http://facebook.com/redirect/url')); + + $actual = $this->Service->getAuthorizationUrl($this->Request); + $expected = 'http://facebook.com/redirect/url'; + $this->assertEquals($expected, $actual); + + $actual = $this->Request->getSession()->read('oauth2state'); + $expected = '_NEW_STATE_'; + $this->assertEquals($expected, $actual); + + } + + /** + * Test getUser method + * + * @return void + */ + public function testGetUser() + { + $this->Request = $this->Request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Request->getSession()->write('oauth2state','__TEST_STATE__'); + + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + + $user = new FacebookUser([ + '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' + ]); + + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); + + $this->Provider->expects($this->never()) + ->method('getState'); + + $this->Provider->expects($this->at(0)) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo(['code' => 'ZPO9972j3092304230']) + ) + ->will($this->returnValue($Token)); + + $this->Provider->expects($this->at(1)) + ->method('getResourceOwner') + ->with( + $this->equalTo($Token) + ) + ->will($this->returnValue($user)); + + $actual = $this->Service->getUser($this->Request); + + $expected = [ + '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' + ]; + + $this->assertEquals($expected, $actual); + } + + /** + * Test getUser method, state not equal + * + * @return void + */ + public function testGetUserStateNotEqual() + { + $this->Request = $this->Request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__Unknown_State__' + ]); + $this->Request->getSession()->write('oauth2state','__TEST_STATE__'); + + + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); + + $this->Provider->expects($this->never()) + ->method('getState'); + + $this->Provider->expects($this->never()) + ->method('getAccessToken'); + + $this->Provider->expects($this->never()) + ->method('getResourceOwner'); + + $this->expectException(BadRequestException::class); + $this->Service->getUser($this->Request); + } + + /** + * Test getUser method without code + * + * @return void + */ + public function testGetUserWithoutCode() + { + $this->Request = $this->Request->withQueryParams([ + 'state' => '__TEST_STATE__' + ]); + $this->Request->getSession()->write('oauth2state','__TEST_STATE__'); + + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); + + $this->Provider->expects($this->never()) + ->method('getState'); + + $this->Provider->expects($this->never()) + ->method('getAccessToken'); + + $this->Provider->expects($this->never()) + ->method('getResourceOwner'); + + $this->expectException(BadRequestException::class); + $this->Service->getUser($this->Request); + } +} diff --git a/tests/TestCase/Social/Service/ServiceFactoryTest.php b/tests/TestCase/Social/Service/ServiceFactoryTest.php new file mode 100644 index 000000000..940d3397f --- /dev/null +++ b/tests/TestCase/Social/Service/ServiceFactoryTest.php @@ -0,0 +1,250 @@ +Factory = new ServiceFactory(); + } + + /** + * Test createFromRequest method + * + * @return void + */ + public function testCreateFromRequest() + { + $config = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => [ + 'state' => '__TEST_STATE__', + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + Configure::write('OAuth.providers.facebook', $config); + + $request = ServerRequestFactory::fromGlobals(); + $request = $request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $request = $request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + + $service = $this->Factory->createFromRequest($request); + $this->assertInstanceOf(OAuth2Service::class, $service); + $this->assertEquals('facebook', $service->getProviderName()); + + $expected = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => [ + 'state' => '__TEST_STATE__', + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + $actual = $service->getConfig(); + $this->assertEquals($expected, $actual); + } + + /** + * Test createFromRequest method + * + * @return void + */ + public function testCreateFromRequestCustomRedirectUriField() + { + $config = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => [ + 'state' => '__TEST_STATE__', + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + Configure::write('OAuth.providers.facebook', $config); + + $request = ServerRequestFactory::fromGlobals(); + $request = $request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $request = $request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + + $this->Factory->setRedirectUriField('callbackLinkSocialUri'); + $service = $this->Factory->createFromRequest($request); + $this->assertInstanceOf(OAuth2Service::class, $service); + $this->assertEquals('facebook', $service->getProviderName()); + + $expected = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => [ + 'state' => '__TEST_STATE__', + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + $actual = $service->getConfig(); + $this->assertEquals($expected, $actual); + } + + /** + * Test createFromRequest method, with oauth1 + * + * @return void + */ + public function testCreateFromRequestOAuth1() + { + $config = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', + 'className' => 'League\OAuth1\Client\Server\Twitter', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Twitter', + 'options' => [ + 'redirectUri' => '/auth/twitter', + 'linkSocialUri' => '/link-social/twitter', + 'callbackLinkSocialUri' => '/callback-link-social/twitter', + 'clientId' => '20003030300303', + 'clientSecret' => 'weakpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + Configure::write('OAuth.providers.twitter', $config); + + $request = ServerRequestFactory::fromGlobals(); + $request = $request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'twitter' + ]); + + $actual = $this->Factory->createFromRequest($request); + $this->assertInstanceOf(OAuth1Service::class, $actual); + $this->assertEquals('twitter', $actual->getProviderName()); + } + + /** + * Test createFromRequest method, provider not enabled + * + * @return void + */ + public function testCreateFromRequestProviderNotEnabled() + { + $request = ServerRequestFactory::fromGlobals(); + $request = $request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $request = $request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + + Configure::delete('OAuth.providers.facebook.options.redirectUri'); + Configure::delete('OAuth.providers.facebook.options.linkSocialUri'); + Configure::delete('OAuth.providers.facebook.options.callbackLinkSocialUri'); + Configure::write('OAuth.providers.facebook', []); + + $this->expectException(NotFoundException::class); + $this->Factory->createFromRequest($request); + } +} From 8c429ef83dd8d8a99c43ae06009e1502a64c4490 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 May 2018 12:07:50 -0300 Subject: [PATCH 006/685] Added custom authenticators --- .../Authenticator/FormAuthenticatorTest.php | 293 ++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 tests/TestCase/Authenticator/FormAuthenticatorTest.php diff --git a/tests/TestCase/Authenticator/FormAuthenticatorTest.php b/tests/TestCase/Authenticator/FormAuthenticatorTest.php new file mode 100644 index 000000000..8e1c7658e --- /dev/null +++ b/tests/TestCase/Authenticator/FormAuthenticatorTest.php @@ -0,0 +1,293 @@ +getMockBuilder(\Authentication\Authenticator\FormAuthenticator::class) + ->setConstructorArgs([$identifiers]) + ->setMethods(['authenticate']) + ->getMock(); + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/testpath'], + [], + ['username' => 'marcelo', 'password' => 'password', 'g-recaptcha-response' => 'BD-S2333-156465897897'] + ); + $response = new Response(); + + $baseResult = new Result( + null, + Result::FAILURE_OTHER + ); + $BaseAuthenticator->expects($this->once()) + ->method('authenticate') + ->with($request, $response) + ->will($this->returnValue($baseResult)); + + $Authenticator = $this->getMockBuilder(FormAuthenticator::class)->setConstructorArgs([ + $identifiers, + [ + 'fields' => [ + IdentifierInterface::CREDENTIAL_USERNAME => 'email', + IdentifierInterface::CREDENTIAL_PASSWORD => 'password' + ] + ] + ])->setMethods(['createBaseAuthenticator', 'validateReCaptcha'])->getMock(); + + Configure::write('Users.reCaptcha.login', true); + $Authenticator->expects($this->once()) + ->method('createBaseAuthenticator') + ->with( + $this->equalTo($identifiers), + $this->equalTo([ + 'fields' => [ + IdentifierInterface::CREDENTIAL_USERNAME => 'email', + IdentifierInterface::CREDENTIAL_PASSWORD => 'password' + ] + ]) + )->will($this->returnValue($BaseAuthenticator)); + + $Authenticator->expects($this->never()) + ->method('validateReCaptcha'); + + $result = $Authenticator->authenticate($request, $response); + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals(Result::FAILURE_OTHER, $result->getStatus()); + $this->assertSame($baseResult, $result); + $this->assertSame($baseResult, $Authenticator->getLastResult()); + } + + /** + * testAuthenticate + * + * @return void + */ + public function testAuthenticate() + { + + $identifiers = new IdentifierCollection([ + 'Authentication.Password' + ]); + + $BaseAuthenticator = $this->getMockBuilder(\Authentication\Authenticator\FormAuthenticator::class) + ->setConstructorArgs([$identifiers]) + ->setMethods(['authenticate']) + ->getMock(); + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/testpath'], + [], + ['username' => 'marcelo', 'password' => 'password', 'g-recaptcha-response' => 'BD-S2333-156465897897'] + ); + $response = new Response(); + + $baseResult = new Result( + [ + 'id' => '42', + 'username' => 'marcelo', + 'role' => 'user' + ], + Result::SUCCESS + ); + $BaseAuthenticator->expects($this->once()) + ->method('authenticate') + ->with($request, $response) + ->will($this->returnValue($baseResult)); + + $Authenticator = $this->getMockBuilder(FormAuthenticator::class)->setConstructorArgs([ + $identifiers, + [ + 'fields' => [ + IdentifierInterface::CREDENTIAL_USERNAME => 'email', + IdentifierInterface::CREDENTIAL_PASSWORD => 'password' + ] + ] + ])->setMethods(['createBaseAuthenticator', 'validateReCaptcha'])->getMock(); + + Configure::write('Users.reCaptcha.login', true); + $Authenticator->expects($this->once()) + ->method('createBaseAuthenticator') + ->with( + $this->equalTo($identifiers), + $this->equalTo([ + 'fields' => [ + IdentifierInterface::CREDENTIAL_USERNAME => 'email', + IdentifierInterface::CREDENTIAL_PASSWORD => 'password' + ] + ]) + )->will($this->returnValue($BaseAuthenticator)); + + $Authenticator->expects($this->once()) + ->method('validateReCaptcha') + ->with( + $this->equalTo('BD-S2333-156465897897') + ) + ->will($this->returnValue(true)); + + $result = $Authenticator->authenticate($request, $response); + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals(Result::SUCCESS, $result->getStatus()); + $this->assertSame($baseResult, $result); + $this->assertSame($baseResult, $Authenticator->getLastResult()); + } + + /** + * testAuthenticate + * + * @return void + */ + public function testAuthenticateNotRequiredReCaptcha() + { + + $identifiers = new IdentifierCollection([ + 'Authentication.Password' + ]); + + $BaseAuthenticator = $this->getMockBuilder(\Authentication\Authenticator\FormAuthenticator::class) + ->setConstructorArgs([$identifiers]) + ->setMethods(['authenticate']) + ->getMock(); + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/testpath'], + [], + ['username' => 'marcelo', 'password' => 'password', 'g-recaptcha-response' => 'BD-S2333-156465897897'] + ); + $response = new Response(); + + $baseResult = new Result( + [ + 'id' => '42', + 'username' => 'marcelo', + 'role' => 'user' + ], + Result::SUCCESS + ); + $BaseAuthenticator->expects($this->once()) + ->method('authenticate') + ->with($request, $response) + ->will($this->returnValue($baseResult)); + + $Authenticator = $this->getMockBuilder(FormAuthenticator::class)->setConstructorArgs([ + $identifiers, + [ + 'fields' => [ + IdentifierInterface::CREDENTIAL_USERNAME => 'email', + IdentifierInterface::CREDENTIAL_PASSWORD => 'password' + ] + ] + ])->setMethods(['createBaseAuthenticator', 'validateReCaptcha'])->getMock(); + + Configure::write('Users.reCaptcha.login', false); + $Authenticator->expects($this->once()) + ->method('createBaseAuthenticator') + ->with( + $this->equalTo($identifiers), + $this->equalTo([ + 'fields' => [ + IdentifierInterface::CREDENTIAL_USERNAME => 'email', + IdentifierInterface::CREDENTIAL_PASSWORD => 'password' + ] + ]) + )->will($this->returnValue($BaseAuthenticator)); + + $Authenticator->expects($this->never()) + ->method('validateReCaptcha'); + + $result = $Authenticator->authenticate($request, $response); + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals(Result::SUCCESS, $result->getStatus()); + $this->assertSame($baseResult, $result); + $this->assertSame($baseResult, $Authenticator->getLastResult()); + } + + /** + * testAuthenticate + * + * @return void + */ + public function testAuthenticateInvalidRecaptcha() + { + + $identifiers = new IdentifierCollection([ + 'Authentication.Password' + ]); + + $BaseAuthenticator = $this->getMockBuilder(\Authentication\Authenticator\FormAuthenticator::class) + ->setConstructorArgs([$identifiers]) + ->setMethods(['authenticate']) + ->getMock(); + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/testpath'], + [], + ['username' => 'marcelo', 'password' => 'password', 'g-recaptcha-response' => 'BD-S2333-156465897897'] + ); + $response = new Response(); + + $baseResult = new Result( + [ + 'id' => '42', + 'username' => 'marcelo', + 'role' => 'user' + ], + Result::SUCCESS + ); + $BaseAuthenticator->expects($this->once()) + ->method('authenticate') + ->with($request, $response) + ->will($this->returnValue($baseResult)); + + $Authenticator = $this->getMockBuilder(FormAuthenticator::class)->setConstructorArgs([ + $identifiers, + [ + 'fields' => [ + IdentifierInterface::CREDENTIAL_USERNAME => 'email', + IdentifierInterface::CREDENTIAL_PASSWORD => 'password' + ] + ] + ])->setMethods(['createBaseAuthenticator', 'validateReCaptcha'])->getMock(); + + Configure::write('Users.reCaptcha.login', true); + $Authenticator->expects($this->once()) + ->method('createBaseAuthenticator') + ->with( + $this->equalTo($identifiers), + $this->equalTo([ + 'fields' => [ + IdentifierInterface::CREDENTIAL_USERNAME => 'email', + IdentifierInterface::CREDENTIAL_PASSWORD => 'password' + ] + ]) + )->will($this->returnValue($BaseAuthenticator)); + + $Authenticator->expects($this->once()) + ->method('validateReCaptcha') + ->with( + $this->equalTo('BD-S2333-156465897897') + ) + ->will($this->returnValue(false)); + + $result = $Authenticator->authenticate($request, $response); + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals(FormAuthenticator::FAILURE_INVALID_RECAPTCHA, $result->getStatus()); + $this->assertNull($result->getData()); + $this->assertSame($result, $Authenticator->getLastResult()); + } +} From 2363ababb8b2a500ee1b9ea24d5fe6838d3e5fcb Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 May 2018 12:09:21 -0300 Subject: [PATCH 007/685] Added Social Middleware --- src/Middleware/SocialAuthMiddleware.php | 185 +++++++++ src/Middleware/SocialEmailMiddleware.php | 106 +++++ .../Middleware/SocialAuthMiddlewareTest.php | 325 ++++++++++++++++ .../Middleware/SocialEmailMiddlewareTest.php | 367 ++++++++++++++++++ 4 files changed, 983 insertions(+) create mode 100644 src/Middleware/SocialAuthMiddleware.php create mode 100644 src/Middleware/SocialEmailMiddleware.php create mode 100644 tests/TestCase/Middleware/SocialAuthMiddlewareTest.php create mode 100644 tests/TestCase/Middleware/SocialEmailMiddlewareTest.php diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php new file mode 100644 index 000000000..962c3b73f --- /dev/null +++ b/src/Middleware/SocialAuthMiddleware.php @@ -0,0 +1,185 @@ +getParam('action'); + if ($action !== 'socialLogin' || $request->getParam('plugin') !== 'CakeDC/Users') { + return $next($request, $response); + } + + $this->setConfig(Configure::read('SocialAuthMiddleware')); + + $this->service = (new ServiceFactory())->createFromRequest($request); + if (!$this->service->isGetUserStep($request)) { + return $response->withLocation($this->service->getAuthorizationUrl($request)); + } + + return $this->finishWithResult($this->authenticate($request), $request, $response, $next); + } + + /** + * finish middleware process. + * + * @param int $result authentication result + * @param \Psr\Http\Message\ServerRequestInterface $request The request. + * @param \Psr\Http\Message\ResponseInterface $response The response. + * @param callable $next Callback to invoke the next middleware. + * @return \Psr\Http\Message\ResponseInterface A response + */ + protected function finishWithResult($result, ServerRequest $request, ResponseInterface $response, $next) + { + if ($result) { + $this->authStatus = self::AUTH_SUCCESS; + $request->getSession()->write( + $this->getConfig('sessionAuthKey'), + $result + ); + + $request->getSession()->delete(Configure::read('Users.Key.Session.social')); + $request->getSession()->write('Users.successSocialLogin', true); + } + + $request = $request->withAttribute('socialAuthStatus', $this->authStatus); + $request = $request->withAttribute('socialRawData', $this->rawData); + + return $next($request, $response); + } + + /** + * 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. + */ + protected function authenticate(ServerRequest $request) + { + $user = $this->getUser($request); + if (!$user) { + return false; + } + + $this->rawData = $user; + + return $this->_touch($user); + } + + /** + * Authenticates with OAuth 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 getUser(ServerRequest $request) + { + try { + $rawData = $this->service->getUser($request); + + return $this->_mapUser($rawData); + } 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; + } + } + + /** + * Find or create local user + * + * @param array $data data + * @return array|bool|mixed + * @throws MissingEmailException + */ + protected function _touch(array $data) + { + $locator = new DatabaseLocator($this->getConfig('locator')); + try { + return $locator->getOrCreate($data); + } catch (UserNotActiveException $ex) { + $this->authStatus = self::AUTH_ERROR_USER_NOT_ACTIVE; + $exception = $ex; + } catch (AccountNotActiveException $ex) { + $this->authStatus = self::AUTH_ERROR_ACCOUNT_NOT_ACTIVE; + $exception = $ex; + } catch (MissingEmailException $ex) { + $this->authStatus = self::AUTH_ERROR_MISSING_EMAIL; + $exception = $ex; + } catch(RecordNotFoundException $ex) { + $this->authStatus = self::AUTH_ERROR_FIND_USER; + $exception = $ex; + } + + $args = ['exception' => $exception, 'rawData' => $data]; + $this->dispatchEvent( AuthListener::EVENT_FAILED_SOCIAL_LOGIN, $args); + + return false; + } + + /** + * Map userdata with mapper defined at $providerConfig + * + * @param array $data User data + * @return mixed Either false or an array of user information + */ + protected function _mapUser($data) + { + $providerMapperClass = $this->service->getConfig('mapper'); + $providerMapper = new $providerMapperClass($data); + $user = $providerMapper(); + $user['provider'] = $this->service->getProviderName(); + + return $user; + } +} \ No newline at end of file diff --git a/src/Middleware/SocialEmailMiddleware.php b/src/Middleware/SocialEmailMiddleware.php new file mode 100644 index 000000000..eed8845ad --- /dev/null +++ b/src/Middleware/SocialEmailMiddleware.php @@ -0,0 +1,106 @@ +getParam('action'); + if ($action !== 'socialEmail' || $request->getParam('plugin') !== 'CakeDC/Users') { + return $next($request, $response); + } + + $this->setConfig(Configure::read('SocialAuthMiddleware')); + + return $this->handleAction($request, $response, $next); + } + + /** + * Handle social email step post. + * + * @param int $result authentication result + * @param \Psr\Http\Message\ServerRequestInterface $request The request. + * @param \Psr\Http\Message\ResponseInterface $response The response. + * @param callable $next Callback to invoke the next middleware. + * @return \Psr\Http\Message\ResponseInterface A response + */ + private function handleAction(ServerRequest $request, ResponseInterface $response, $next) + { + if (!$request->getSession()->check(Configure::read('Users.Key.Session.social'))) { + throw new NotFoundException(); + } + $request->getSession()->delete('Flash.auth'); + $result = false; + + if (!$request->is('post')) { + return $this->finishWithResult($result, $request, $response, $next); + } + + if (!$this->_validateRegisterPost($request)) { + $this->authStatus = self::AUTH_ERROR_INVALID_RECAPTCHA; + } else { + $result = $this->authenticate($request); + } + + return $this->finishWithResult($result, $request, $response, $next); + } + + /** + * Check the POST and validate it for registration, for now we check the reCaptcha + * + * @param \Psr\Http\Message\ServerRequestInterface $request The request. + * @return bool + */ + private function _validateRegisterPost($request) + { + if (!Configure::read('Users.reCaptcha.registration')) { + return true; + } + + return $this->validateReCaptcha( + $request->getData('g-recaptcha-response'), + $request->clientIp() + ); + } + + /** + * Authenticates with Session data (from SocialAuthMiddleware) and form email. + * config: Users.Key.Session.social, + * form input name: email + * + * @param \Cake\Http\ServerRequest $request Request object. + * @return array|bool + */ + protected 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; + } + $request->getSession()->delete(Configure::read('Users.Key.Session.social')); + + return $data; + } + + return false; + } +} \ No newline at end of file diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php new file mode 100644 index 000000000..fc2b0b41b --- /dev/null +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -0,0 +1,325 @@ +Provider = $this->getMockBuilder('\League\OAuth2\Client\Provider\Facebook')->setConstructorArgs([ + [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + [] + ])->setMethods([ + 'getAccessToken', 'getState', 'getAuthorizationUrl', 'getResourceOwner' + ])->getMock(); + + $config = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => $this->Provider, + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => [ + 'state' => '__TEST_STATE__', + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + Configure::write('OAuth.providers.facebook', $config); + + $this->Request = ServerRequestFactory::fromGlobals(); + } + + /** + * teardown any static object changes and restore them. + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + + unset($this->Provider, $this->Request); + } + + /** + * Test when user is on step one + * + * @return void + */ + public function testProceedStepOne() + { + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + + $this->Request = $this->Request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + + $this->Provider->expects($this->any()) + ->method('getState') + ->will($this->returnValue('_NEW_STATE_')); + + $this->Provider->expects($this->any()) + ->method('getAuthorizationUrl') + ->will($this->returnValue('http://facebook.com/redirect/url')); + + + $Middleware = new SocialAuthMiddleware(); + $response = new Response(); + $next = function ($request, $response) { + $this->fail('Should not call $next'); + }; + + $result = $Middleware($this->Request, $response, $next); + $this->assertInstanceOf(Response::class, $result); + if (!$result) { + $this->fail('No response set, cannot assert location header. '); + } + + $actual = $this->Request->getSession()->read('oauth2state'); + $expected = '_NEW_STATE_'; + $this->assertEquals($expected, $actual); + + $actual = $result->getHeaderLine('Location'); + $expected = 'http://facebook.com/redirect/url'; + $this->assertEquals($expected, $actual); + } + + /** + * Test when user successfully authenticated + * + * @return void + */ + public function testSuccessfullyAuthenticated() + { + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Request = $this->Request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + $this->Request->getSession()->write('oauth2state','__TEST_STATE__'); + + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $user = new FacebookUser([ + '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' + ]); + + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); + + $this->Provider->expects($this->never()) + ->method('getState'); + + $this->Provider->expects($this->any()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo(['code' => 'ZPO9972j3092304230']) + ) + ->will($this->returnValue($Token)); + + $this->Provider->expects($this->any()) + ->method('getResourceOwner') + ->with( + $this->equalTo($Token) + ) + ->will($this->returnValue($user)); + + $Middleware = new SocialAuthMiddleware(); + + $response = new Response(); + $next = function ($request, $response) { + return compact('request', 'response'); + }; + + $result = $Middleware($this->Request, $response, $next); + $this->assertEquals(SocialAuthMiddleware::AUTH_SUCCESS, $result['request']->getAttribute('socialAuthStatus')); + $this->assertNotEmpty($result['request']->getAttribute('socialRawData')); + $this->assertNotEmpty($result['request']->getAttribute('socialRawData')['id']); + $this->assertInstanceOf(User::class, $this->Request->getSession()->read('Auth')); + $this->assertEquals(200, $result['response']->getStatusCode()); + } + + /** + * Test when has error getting user + * + * @return void + */ + public function testErrorGetUser() + { + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Request = $this->Request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + $this->Request->getSession()->write('oauth2state','__TEST_STATE__'); + + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); + + $this->Provider->expects($this->never()) + ->method('getState'); + + $this->Provider->expects($this->any()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo(['code' => 'ZPO9972j3092304230']) + ) + ->will($this->returnValue($Token)); + + $this->Provider->expects($this->any()) + ->method('getResourceOwner') + ->will($this->throwException(new \Exception('Test error'))); + + $Middleware = new SocialAuthMiddleware(); + + $response = new Response(); + $next = function ($request, $response) { + return compact('request', 'response'); + }; + + $result = $Middleware($this->Request, $response, $next); + $this->assertEquals(0, $result['request']->getAttribute('socialAuthStatus')); + $this->assertEmpty($result['request']->getAttribute('socialRawData')); + $this->assertEmpty($this->Request->getSession()->read('Auth')); + $this->assertEquals(200, $result['response']->getStatusCode()); + } + + /** + * Test when action is not valid for social login + * + * @return void + */ + public function testNotValidAction() + { + $Middleware = new SocialAuthMiddleware(); + $response = new Response(); + $next = function ($request, $response) { + return compact('request', 'response'); + }; + + $result = $Middleware($this->Request, $response, $next); + $this->assertTrue(is_array($result)); + + $this->assertEquals(200, $result['response']->getStatusCode()); + } +} diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php new file mode 100644 index 000000000..434c32095 --- /dev/null +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -0,0 +1,367 @@ + 'CakeDC\Users\Social\Service\OAuth2Service', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => [ + 'state' => '__TEST_STATE__', + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + Configure::write('OAuth.providers.facebook', $config); + + + $this->Request = ServerRequestFactory::fromGlobals(); + } + + /** + * teardown any static object changes and restore them. + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + + unset($this->Request); + } + + /** + * Test when action with get request + * + * @return void + */ + public function testWithGetRquest() + { + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $user = new FacebookUser([ + 'id' => '1', + 'name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => null, + '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' + ]); + $user = [ + 'token' => $Token, + ] + $user->toArray(); + + $user = (new Facebook($user))(); + $user['provider'] = 'facebook'; + $user['validated'] = true; + Configure::write('Users.Email.validate', false); + $this->Request->getSession()->write(Configure::read('Users.Key.Session.social'), $user); + + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialEmail', + ]); + + $Middleware = new SocialEmailMiddleware(); + $response = new Response(); + $next = function ($request, $response) { + return compact('request', 'response'); + }; + + $result = $Middleware($this->Request, $response, $next); + $this->assertTrue(is_array($result)); + + $this->assertEquals(null, $result['request']->getAttribute('socialAuthStatus')); + $this->assertEmpty($result['request']->getAttribute('socialRawData')); + $this->assertEmpty($this->Request->getSession()->read('Auth')); + $this->assertEmpty($this->Request->getSession()->read('Users.successSocialLogin')); + } + + /** + * Test when action without user + * + * @return void + */ + public function testWithoutUser() + { + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->withParsedBody([ + 'email' => 'example@example.com' + ]); + $this->Request = $this->Request->withMethod('POST'); + $this->Request = $this->Request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialEmail', + ]); + + $Middleware = new SocialEmailMiddleware(); + $response = new Response(); + $next = function ($request, $response) { + return compact('request', 'response'); + }; + + $this->expectException(NotFoundException::class); + $Middleware($this->Request, $response, $next); + } + + /** + * Test when action with successfull authentication + * + * @return void + */ + public function testSuccessfullyAuthenticated() + { + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $user = new FacebookUser([ + 'id' => '1', + 'name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => null, + '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' + ]); + $user = [ + 'token' => $Token, + ] + $user->toArray(); + + $user = (new Facebook($user))(); + $user['provider'] = 'facebook'; + $user['validated'] = true; + Configure::write('Users.Email.validate', false); + $this->Request->getSession()->write(Configure::read('Users.Key.Session.social'), $user); + + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->withParsedBody([ + 'email' => 'example@example.com' + ]); + $this->Request = $this->Request->withMethod('POST'); + $this->Request = $this->Request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialEmail', + ]); + + $Middleware = new SocialEmailMiddleware(); + $response = new Response(); + $next = function ($request, $response) { + return compact('request', 'response'); + }; + + $result = $Middleware($this->Request, $response, $next); + $this->assertTrue(is_array($result)); + + $this->assertEquals(200, $result['response']->getStatusCode()); + $this->assertEquals(SocialEmailMiddleware::AUTH_SUCCESS, $result['request']->getAttribute('socialAuthStatus')); + $this->assertNotEmpty($result['request']->getAttribute('socialRawData')); + $this->assertNotEmpty($result['request']->getAttribute('socialRawData')['id']); + $this->assertInstanceOf(User::class, $this->Request->getSession()->read('Auth')); + $this->assertTrue($this->Request->getSession()->read('Users.successSocialLogin')); + } + + /** + * Test when action without email + * + * @return void + */ + public function testWithoutEmail() + { + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $user = new FacebookUser([ + 'id' => '1', + 'name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => null, + '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' + ]); + $user = [ + 'token' => $Token, + ] + $user->toArray(); + + $user = (new Facebook($user))(); + $user['provider'] = 'facebook'; + $user['validated'] = true; + Configure::write('Users.Email.validate', false); + $this->Request->getSession()->write(Configure::read('Users.Key.Session.social'), $user); + + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->withMethod('POST'); + $this->Request = $this->Request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialEmail', + ]); + + $Middleware = new SocialEmailMiddleware(); + $response = new Response(); + $next = function ($request, $response) { + return compact('request', 'response'); + }; + + $result = $Middleware($this->Request, $response, $next); + $this->assertTrue(is_array($result)); + + $this->assertEquals(200, $result['response']->getStatusCode()); + $this->assertEquals(0, $result['request']->getAttribute('socialAuthStatus')); + $this->assertEmpty($result['request']->getAttribute('socialRawData')); + $this->assertEmpty($this->Request->getSession()->read('Auth')); + } + + /** + * Test when action is not valid for social login + * + * @return void + */ + public function testNotValidAction() + { + $Middleware = new SocialEmailMiddleware(); + $response = new Response(); + $next = function ($request, $response) { + return compact('request', 'response'); + }; + + $result = $Middleware($this->Request, $response, $next); + $this->assertTrue(is_array($result)); + + $this->assertEquals(200, $result['response']->getStatusCode()); + $this->assertSame($response, $result['response']); + $this->assertSame($this->Request, $result['request']); + } + +} From 036fa6619292bef03984eb5027a12a558e04e5df Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 May 2018 12:11:36 -0300 Subject: [PATCH 008/685] Google Verify --- src/Controller/Traits/GoogleVerifyTrait.php | 159 ++++++++++++++++++ .../GoogleAuthenticatorMiddleware.php | 57 +++++++ 2 files changed, 216 insertions(+) create mode 100644 src/Controller/Traits/GoogleVerifyTrait.php create mode 100644 src/Middleware/GoogleAuthenticatorMiddleware.php diff --git a/src/Controller/Traits/GoogleVerifyTrait.php b/src/Controller/Traits/GoogleVerifyTrait.php new file mode 100644 index 000000000..6c1263f9c --- /dev/null +++ b/src/Controller/Traits/GoogleVerifyTrait.php @@ -0,0 +1,159 @@ +isVerifyAllowed()) { + return $this->redirect($loginAction); + } + + $temporarySession = $this->request->getSession()->read('temporarySession'); + $secretVerified = $temporarySession['secret_verified']; + + // showing QR-code until shared secret is verified + if (!$secretVerified) { + $secret = $this->onVerifyGetSecret($temporarySession); + if (empty($secret)) { + return $this->redirect($loginAction); + } + $secretDataUri = $this->GoogleAuthenticator->getQRCodeImageAsDataUri( + $temporarySession['email'], + $secret + ); + $this->set(compact('secretDataUri')); + } + + if ($this->request->is('post')) { + return $this->onPostVerifyCode($loginAction); + } + } + + /** + * Check If Google Authenticator's enabled we need to verify + * authenticated user and if temporySession is present + * + * @return bool + */ + protected function isVerifyAllowed() + { + if (!Configure::read('Users.GoogleAuthenticator.login')) { + $message = __d('CakeDC/Users', 'Please enable Google Authenticator first.'); + $this->Flash->error($message, 'default', [], 'auth'); + + return true; + } + + $temporarySession = $this->request->getSession()->read('temporarySession'); + + if (empty($temporarySession)) { + $message = __d('CakeDC/Users', 'Could not find user data'); + $this->Flash->error($message, 'default', [], 'auth'); + + return true; + } + + return false; + } + + /** + * Get the Google Authenticator secret of user, if not exists try to create one and save + * + * @param User $user user data present on session + * + * @return string if empty the creation has failed + */ + protected function onVerifyGetSecret($user) + { + if ($user['secret']) { + return $user['secret']; + } + + $secret = $this->GoogleAuthenticator->createSecret(); + + // catching sql exception in case of any sql inconsistencies + try { + $query = $this->getUsersTable()->query(); + $query->update() + ->set(['secret' => $secret]) + ->where(['id' => $user['id']]); + $query->execute(); + } catch (\Exception $e) { + $this->request->getSession()->destroy(); + $message = $e->getMessage(); + $this->Flash->error($message, 'default', [], 'auth'); + + return ''; + } + + return $secret; + } + + /** + * Handle the action when user post the form with code + * + * @param array $loginAction url to login page used in redirect + * + * @return \Cake\Http\Response + */ + protected function onPostVerifyCode($loginAction) + { + $codeVerified = false; + $verificationCode = $this->request->getData('code'); + $user = $this->request->getSession()->read('temporarySession'); + $entity = $this->getUsersTable()->get($user['id']); + + if (!empty($entity['secret'])) { + $codeVerified = $this->GoogleAuthenticator->verifyCode($entity['secret'], $verificationCode); + } + + if (!$codeVerified) { + $this->request->getSession()->destroy(); + $message = __d('CakeDC/Users', 'Verification code is invalid. Try again'); + $this->Flash->error($message, 'default', [], 'auth'); + + return $this->redirect($loginAction); + } + + return $this->onPostVerifyCodeOkay($loginAction, $user); + } + + /** + * Handle the part of action when user post the form with valid code + * + * @param array $loginAction url to login page used in redirect + * @param User $user user data present on session + * + * @return \Cake\Http\Response + */ + protected function onPostVerifyCodeOkay($loginAction, $user) + { + unset($user['secret']); + + if (!$user['secret_verified']) { + $this->getUsersTable()->query()->update() + ->set(['secret_verified' => true]) + ->where(['id' => $user['id']]) + ->execute(); + } + + $this->request->getSession()->delete('temporarySession'); + $this->request->getSession()->write('GoogleTwoFactor.User', $user); + + return $this->redirect($loginAction); + } +} \ No newline at end of file diff --git a/src/Middleware/GoogleAuthenticatorMiddleware.php b/src/Middleware/GoogleAuthenticatorMiddleware.php new file mode 100644 index 000000000..8e58cb76e --- /dev/null +++ b/src/Middleware/GoogleAuthenticatorMiddleware.php @@ -0,0 +1,57 @@ +getAttribute('identity'); + if (!$identity) { + return $next($request, $response); + } + + $service = $request->getAttribute('authentication'); + + if ($service->getAuthenticationProvider()->getConfig('skipGoogleVerify') === true) { + return $next($request, $response); + } + + $result = $service->clearIdentity($request, $response); + $request = $result['request']; + $response = $result['response']; + $request = $request->withoutAttribute('identity'); + $request = $request->withoutAttribute('authentication'); + $request = $request->withoutAttribute('authenticationResult'); + $request->getSession()->write('temporarySession', $identity->getOriginalData()); + $request->getSession()->write('CookieAuth', [ + 'remember_me' => $request->getData('remember_me') + ]); + + $url = Router::url(['action' => 'verify']); + + return $response + ->withHeader('Location', $url) + ->withStatus(302); + + } + +} \ No newline at end of file From 8291ce88dd13ed4974b3d2dc8a3774abf969b3c0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 May 2018 12:13:46 -0300 Subject: [PATCH 009/685] Link Social Account Using Social Services --- src/Controller/Traits/LinkSocialTrait.php | 162 +--- .../Controller/Traits/BaseTraitTest.php | 18 + .../Controller/Traits/LinkSocialTraitTest.php | 832 ++++++------------ 3 files changed, 311 insertions(+), 701 deletions(-) diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 9b10c960b..33c6d522d 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -11,9 +11,11 @@ namespace CakeDC\Users\Controller\Traits; +use Cake\Utility\Hash; use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; +use CakeDC\Users\Social\Service\ServiceFactory; use League\OAuth1\Client\Server\Twitter; /** @@ -32,19 +34,12 @@ trait LinkSocialTrait */ public function linkSocial($alias = null) { - $provider = $this->_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); + return $this->redirect( + (new ServiceFactory()) + ->setRedirectUriField('callbackLinkSocialUri') + ->createFromProvider($alias) + ->getAuthorizationUrl($this->request) + ); } /** @@ -58,62 +53,20 @@ public function linkSocial($alias = null) 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()) { + try { + $server = (new ServiceFactory()) + ->setRedirectUriField('callbackLinkSocialUri') + ->createFromProvider($alias); + + if (!$server->isGetUserStep($this->request)) { $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 = $server->getUser($this->request); $data = $this->_mapSocialUser($alias, $data); - - $user = $this->getUsersTable()->get($this->Auth->user('id')); + $userId = Hash::get($this->request->getAttribute('identity') ?? [], 'id'); + $user = $this->getUsersTable()->get($userId); $this->getUsersTable()->linkSocialAccount($user, $data); @@ -124,7 +77,7 @@ public function callbackLinkSocial($alias = null) } } catch (\Exception $e) { $log = sprintf( - "Error retrieving the authorized user's profile data. Error message: %s %s", + "Error linking social account: %s %s", $e->getMessage(), $e ); @@ -155,83 +108,4 @@ protected function _mapSocialUser($alias, $data) 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/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index a7ff42461..201e7a3bc 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -11,11 +11,13 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; +use Authentication\Identity; use Cake\Event\Event; use Cake\Mailer\Email; use Cake\ORM\Entity; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; +use CakeDC\Users\Model\Entity\User; use PHPUnit_Framework_MockObject_RuntimeException; abstract class BaseTraitTest extends TestCase @@ -184,6 +186,22 @@ protected function _mockAuthLoggedIn($user = []) ->will($this->returnValue($user['id'])); } + /** + * Mock Auth and retur user id 1 + * + * @return void + */ + protected function _setAuthenticationIdentity($user = []) + { + $user += [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'password' => '12345', + ]; + + $identity = new Identity(new User($user)); + $this->Trait->request = $this->Trait->request->withAttribute('identity', $identity); + } + /** * Mock the Auth component * diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 00ce7b11b..b78d49310 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -11,27 +11,18 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use CakeDC\Users\Controller\Traits\LinkSocialTrait; +use Cake\Http\Response; +use Cake\Http\ServerRequestFactory; use Cake\Core\Configure; use Cake\Event\Event; -use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequest; use Cake\I18n\Time; use Cake\ORM\TableRegistry; -use Cake\TestSuite\TestCase; -use League\OAuth2\Client\Provider\Facebook; use League\OAuth2\Client\Provider\FacebookUser; -use League\OAuth2\Client\Token\AccessToken; +use Zend\Diactoros\Uri; class LinkSocialTraitTest extends BaseTraitTest { - /** - * Keep the original config for oauth - * - * @var array - */ - private $oauthConfig; - /** * Fixtures * @@ -42,6 +33,11 @@ class LinkSocialTraitTest extends BaseTraitTest 'plugin.CakeDC/Users.users' ]; + /** + * @var \League\OAuth2\Client\Provider\Facebook + */ + public $Provider; + /** * setup * @@ -49,9 +45,6 @@ class LinkSocialTraitTest extends BaseTraitTest */ public function setUp() { - if ($this->oauthConfig === null) { - $this->oauthConfig = Configure::read('OAuth'); - } $this->traitClassName = 'CakeDC\Users\Controller\Traits\LinkSocialTrait'; $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; @@ -67,39 +60,45 @@ public function setUp() ->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)); + $this->Provider = $this->getMockBuilder('\League\OAuth2\Client\Provider\Facebook')->setConstructorArgs([ + [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + [] + ])->setMethods([ + 'getAccessToken', 'getState', 'getAuthorizationUrl', 'getResourceOwner' + ])->getMock(); + + $config = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => $this->Provider, + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'options' => [ + 'state' => '__TEST_STATE__', + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + Configure::write('OAuth.providers.facebook', $config); } /** @@ -116,52 +115,44 @@ public function testLinkSocialHappy() ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) ->getMockForTrait(); - $this->_mockRequestGet(true); - $this->_mockAuthLoggedIn(); + $this->Trait->request = ServerRequestFactory::fromGlobals(); + $this->Trait->request->getSession()->write('oauth2state','__TEST_STATE__'); + $uri = new Uri('/callback-link-social/facebook'); + + $this->Trait->request = $this->Trait->request->withUri($uri); + $this->Trait->request = $this->Trait->request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Trait->request = $this->Trait->request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'linkSocial', + 'provider' => 'facebook' + ]); + + $this->_setAuthenticationIdentity(); $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(); + $this->Provider->expects($this->any()) + ->method('getState') + ->will($this->returnValue('_NEW_STATE_')); - $ProviderMock->expects($this->once()) + $this->Provider->expects($this->any()) ->method('getAuthorizationUrl') - ->will($this->returnValue('http://localhost/fake/facebook/login')); + ->will($this->returnValue('http://facebook.com/redirect/url')); - $ProviderMock->expects($this->once()) - ->method('getState') - ->will($this->returnValue('a3423ja9ads90u3242309')); + $this->Trait->Flash->expects($this->never()) + ->method('error'); - $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->Flash->expects($this->never()) + ->method('success'); $this->Trait->expects($this->once()) ->method('redirect') - ->with( - $this->equalTo('http://localhost/fake/facebook/login') - ); + ->with($this->equalTo('http://facebook.com/redirect/url')) + ->will($this->returnValue(new Response())); $this->Trait->linkSocial('facebook'); } @@ -171,119 +162,99 @@ public function testLinkSocialHappy() * * @return void */ - public function testLinkSocialNotDefineLinkSocialRedirectUri() + public function testCallbackLinkSocialHappy() { 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(); + $Table = TableRegistry::get('CakeDC/Users.Users'); - $this->_mockDispatchEvent(new Event('event')); - - $this->Trait->linkSocial('facebook'); - } catch (NotFoundException $e) { - $result = true; - } - $this->assertTrue($result); - } + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); - /** - * 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(); + $user = 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', + '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' => 'facebook-link-15579', + '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' + ]); - $this->_mockDispatchEvent(new Event('event')); + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); - $this->Trait->linkSocial('facebook'); - } catch (NotFoundException $e) { - $result = true; - } - $this->assertTrue($result); - } + $this->Provider->expects($this->never()) + ->method('getState'); - /** - * 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'); + $this->Provider->expects($this->any()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo(['code' => 'ZPO9972j3092304230']) + ) + ->will($this->returnValue($Token)); - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->Provider->expects($this->any()) + ->method('getResourceOwner') + ->with( + $this->equalTo($Token) + ) + ->will($this->returnValue($user)); $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->setMethods(['dispatchEvent', 'redirect', 'set', 'getUsersTable', 'log']) ->getMockForTrait(); + $this->Trait->request = ServerRequestFactory::fromGlobals(); + $this->Trait->request->getSession()->write('oauth2state','__TEST_STATE__'); + $uri = new Uri('/callback-link-social/facebook'); + + $this->Trait->request = $this->Trait->request->withUri($uri); + $this->Trait->request = $this->Trait->request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Trait->request = $this->Trait->request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'linkSocial', + 'provider' => 'facebook' + ]); + $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->_setAuthenticationIdentity(); $this->_mockDispatchEvent(new Event('event')); $this->_mockFlash(); $this->Trait->Flash->expects($this->never()) @@ -293,73 +264,20 @@ public function testCallbackLinkSocialHappy() ->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'); + $tokenExpires = $expiresTime->setTimestamp($Token->getExpires())->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', + 'description' => 'I am the best test user in the world.', + 'token' => 'test-token', 'token_secret' => null, 'user_id' => '00000000-0000-0000-0000-000000000001', 'active' => true @@ -380,7 +298,7 @@ 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 = TableRegistry::get('akeDC/Users.Users')->get('00000000-0000-0000-0000-000000000001'); $user->setErrors([ 'social_accounts' => [ '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') @@ -397,67 +315,12 @@ public function testCallbackLinkSocialWithValidationErrors() ->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' - ] + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 ]); - $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([ + $user = new FacebookUser([ 'id' => '9999911112255', 'name' => 'Ful Name.', 'username' => 'mock_username', @@ -465,125 +328,87 @@ public function testCallbackLinkSocialWithValidationErrors() 'last_name' => 'Last name', 'email' => 'user-1@test.com', 'Location' => 'mock_home', - 'bio' => 'mock_description', + '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' => 'facebook-link-15579', + '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' ]); - $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'); + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); - $actual = $Table->SocialAccounts->exists(['reference' => '9999911112255']); - $this->assertFalse($actual); - } + $this->Provider->expects($this->never()) + ->method('getState'); - /** - * test - * - * @return void - */ - public function testCallbackLinkSocialFailGettingAccessToken() - { - Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); + $this->Provider->expects($this->any()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo(['code' => 'ZPO9972j3092304230']) + ) + ->will($this->returnValue($Token)); - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->Provider->expects($this->any()) + ->method('getResourceOwner') + ->with( + $this->equalTo($Token) + ) + ->will($this->returnValue($user)); $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LinkSocialTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set', '_createSocialProvider', 'getUsersTable', 'log']) + ->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->Trait->request = ServerRequestFactory::fromGlobals(); + $this->Trait->request->getSession()->write('oauth2state','__TEST_STATE__'); + $uri = new Uri('/callback-link-social/facebook'); - $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->Trait->request = $this->Trait->request->withUri($uri); + $this->Trait->request = $this->Trait->request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Trait->request = $this->Trait->request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'linkSocial', + 'provider' => 'facebook' ]); - $this->_mockAuthLoggedIn(); + + $this->_setAuthenticationIdentity(); $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.')); + ->method('error'); $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']); @@ -600,131 +425,46 @@ 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'); + $Table = TableRegistry::get('CakeDC/Users.Users'); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); - $ProviderMock = $this->getMockBuilder('League\OAuth2\Client\Provider\Facebook') - ->setMethods(['getAccessToken', 'getResourceOwner']) - ->disableOriginalConstructor() - ->getMock(); + $this->Provider->expects($this->never()) + ->method('getState'); - $ProviderMock->expects($this->never()) + $this->Provider->expects($this->never()) ->method('getAccessToken'); - $ProviderMock->expects($this->never()) + $this->Provider->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']) + ->setMethods(['dispatchEvent', 'redirect', 'set', 'getUsersTable', 'log']) ->getMockForTrait(); + $this->Trait->request = ServerRequestFactory::fromGlobals(); + $this->Trait->request->getSession()->write('oauth2state','__TEST_STATE__'); + $uri = new Uri('/callback-link-social/facebook'); + + $this->Trait->request = $this->Trait->request->withUri($uri); + $this->Trait->request = $this->Trait->request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'linkSocial', + 'provider' => 'facebook' + ]); + $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(); + ->with($this->equalTo([ + 'action' => 'profile' + ])) + ->will($this->returnValue(new Response())); + $this->_setAuthenticationIdentity(); $this->_mockDispatchEvent(new Event('event')); $this->_mockFlash(); $this->Trait->Flash->expects($this->never()) @@ -734,35 +474,8 @@ public function testCallbackLinkSocialWrongState() ->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'); + $result = $this->Trait->callbackLinkSocial('facebook'); + $this->assertInstanceOf(Response::class, $result); } /** @@ -770,47 +483,51 @@ public function testCallbackLinkSocialWrongState() * * @return void */ - public function testCallbackLinkSocialMissingCode() + public function testCallbackLinkSocialUnknownProvider() { Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $Table = TableRegistry::get('CakeDC/Users.Users'); + + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); + + $this->Provider->expects($this->never()) + ->method('getState'); + + $this->Provider->expects($this->never()) + ->method('getAccessToken'); + + $this->Provider->expects($this->never()) + ->method('getResourceOwner'); $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->request = ServerRequestFactory::fromGlobals(); + $this->Trait->request->getSession()->write('oauth2state','__TEST_STATE__'); + $uri = new Uri('/callback-link-social/facebook'); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['setConfig']) - ->disableOriginalConstructor() - ->getMock(); + $this->Trait->request = $this->Trait->request->withUri($uri); + $this->Trait->request = $this->Trait->request->addParams([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'linkSocial', + 'provider' => 'unknown' + ]); - $this->_mockRequestGet(true); - $this->Trait->request->expects($this->never()) - ->method('getQuery'); + $this->Trait->expects($this->never()) + ->method('getUsersTable'); - $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(); + ->with($this->equalTo([ + 'action' => 'profile' + ])) + ->will($this->returnValue(new Response())); + $this->_setAuthenticationIdentity(); $this->_mockDispatchEvent(new Event('event')); $this->_mockFlash(); $this->Trait->Flash->expects($this->never()) @@ -820,6 +537,7 @@ public function testCallbackLinkSocialMissingCode() ->method('error') ->with(__d('CakeDC/Users', 'Could not associate account, please try again.')); - $this->Trait->callbackLinkSocial('facebook'); + $result = $this->Trait->callbackLinkSocial('unknown'); + $this->assertInstanceOf(Response::class, $result); } } From 905f8b337e745c4756ebfb867b51cccee4d8fef8 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 May 2018 12:14:26 -0300 Subject: [PATCH 010/685] Auth Helper using RBAC --- src/Traits/IsAuthorizedTrait.php | 76 ++++++++++++++++++++++++++++++ src/View/Helper/AuthLinkHelper.php | 21 ++------- 2 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 src/Traits/IsAuthorizedTrait.php diff --git a/src/Traits/IsAuthorizedTrait.php b/src/Traits/IsAuthorizedTrait.php new file mode 100644 index 000000000..aac096cc3 --- /dev/null +++ b/src/Traits/IsAuthorizedTrait.php @@ -0,0 +1,76 @@ +checkRbacPermissions(Router::normalize(Router::reverse($url))); + } + + try { + //remove base from $url if exists + $normalizedUrl = Router::normalize($url); + + return $this->checkRbacPermissions($url); + } catch (MissingRouteException $ex) { + //if it's a url pointing to our own app + if (substr($normalizedUrl, 0, 1) === '/') { + throw $ex; + } + + return true; + } + } + + /** + * Check if current user permissions of url + * + * @param string $url to check permissions + * + * @return bool + */ + protected function checkRbacPermissions($url) + { + $uri = new Uri($url); + $Rbac = $this->request ? $this->request->getAttribute('rbac') : null; + if ($Rbac === null) { + $Rbac = new Rbac(); + } + $targetRequest = new ServerRequest([ + 'uri' => $uri + ]); + $params = Router::parseRequest($targetRequest); + $targetRequest = $targetRequest->withAttribute('params', $params); + + $user = $this->request->getAttribute('identity'); + $userData = []; + if ($user) { + $userData = Hash::get($user, 'User', []); + $userData = is_object($userData) ? $userData->toArray() : $userData; + } + + return $Rbac->checkPermissions($userData, $targetRequest); + } + +} \ No newline at end of file diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index b9b8e0c97..f61655ade 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -11,12 +11,9 @@ namespace CakeDC\Users\View\Helper; -use CakeDC\Users\Controller\Component\UsersAuthComponent; -use Cake\Event\Event; -use Cake\Event\EventManager; use Cake\Utility\Hash; -use Cake\View\Helper; use Cake\View\Helper\HtmlHelper; +use CakeDC\Users\Traits\IsAuthorizedTrait; /** * AuthLink helper @@ -24,6 +21,8 @@ class AuthLinkHelper extends HtmlHelper { + use IsAuthorizedTrait; + /** * Generate a link if the target url is authorized for the logged in user * @@ -51,18 +50,4 @@ public function link($title, $url = null, array $options = []) 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; - } } From 32be4afeb5bb37c4b87accf4df3d7de36c7b3a24 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 May 2018 12:15:38 -0300 Subject: [PATCH 011/685] Google Verify --- src/Controller/UsersController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index b86bd0940..967c7e8a3 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -13,6 +13,7 @@ use CakeDC\Users\Controller\AppController; use CakeDC\Users\Controller\Component\UsersAuthComponent; +use CakeDC\Users\Controller\Traits\GoogleVerifyTrait; use CakeDC\Users\Controller\Traits\LinkSocialTrait; use CakeDC\Users\Controller\Traits\LoginTrait; use CakeDC\Users\Controller\Traits\ProfileTrait; @@ -31,6 +32,7 @@ */ class UsersController extends AppController { + use GoogleVerifyTrait; use LinkSocialTrait; use LoginTrait; use ProfileTrait; From 8b96319cc9a6e606b050151258e6d32e4bcc4bec Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 May 2018 12:17:21 -0300 Subject: [PATCH 012/685] Moved from AuthComponent to authentication plugin + RBAC --- composer.json | 10 +- config/bootstrap.php | 8 - config/permissions.php | 36 +++ config/routes.php | 10 +- config/users.php | 66 ++++- src/Controller/AppController.php | 7 +- .../Component/UsersAuthComponent.php | 185 ------------ src/Controller/SocialAccountsController.php | 1 - src/Controller/Traits/LoginTrait.php | 279 +++++------------- .../Traits/PasswordManagementTrait.php | 10 +- src/Controller/Traits/ProfileTrait.php | 2 +- src/Controller/Traits/RegisterTrait.php | 3 +- src/Controller/Traits/SocialTrait.php | 18 +- src/Http/BaseApplication.php | 103 +++++++ src/Listener/AuthListener.php | 22 ++ tests/App/Controller/AppController.php | 1 - 16 files changed, 313 insertions(+), 448 deletions(-) create mode 100644 src/Http/BaseApplication.php create mode 100644 src/Listener/AuthListener.php diff --git a/composer.json b/composer.json index 93d1a1dbd..018589319 100644 --- a/composer.json +++ b/composer.json @@ -32,13 +32,17 @@ }, "require-dev": { "phpunit/phpunit": "^5.0", + "cakephp/cakephp-codesniffer": "^2.0", "league/oauth2-facebook": "@stable", "league/oauth2-instagram": "@stable", "league/oauth2-google": "@stable", "league/oauth2-linkedin": "@stable", "luchianenco/oauth2-amazon": "^1.1", "google/recaptcha": "@stable", - "robthree/twofactorauth": "~1.6.0" + "robthree/twofactorauth": "~1.6.0", + "satooshi/php-coveralls": "^2.0", + "cakephp/authentication": "^1.0@RC", + "league/oauth1-client": "^1.7" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", @@ -60,5 +64,7 @@ "CakeDC\\Users\\Test\\": "tests", "CakeDC\\Users\\Test\\Fixture\\": "tests" } - } + }, + "minimum-stability": "dev", + "prefer-stable": true } diff --git a/config/bootstrap.php b/config/bootstrap.php index 42d2bb0c2..606b5f220 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -29,14 +29,6 @@ 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) { diff --git a/config/permissions.php b/config/permissions.php index 79a4ae957..04a6bf41f 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -51,6 +51,42 @@ return [ 'CakeDC/Auth.permissions' => [ + //all bypass + [ + 'prefix' => false, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => [ + // LoginTrait + 'socialLogin', + 'login', + 'socialEmail', + 'verify', + // RegisterTrait + 'register', + 'validateEmail', + // PasswordManagementTrait used in RegisterTrait + 'changePassword', + 'resetPassword', + 'requestResetPassword', + // UserValidationTrait used in PasswordManagementTrait + 'resendTokenValidation', + // Social + 'endpoint', + 'authenticated', + ], + 'bypassAuth' => true, + ], + [ + 'prefix' => false, + 'plugin' => 'CakeDC/Users', + 'controller' => 'SocialAccounts', + 'action' => [ + 'validateAccount', + 'resendValidation', + ], + 'bypassAuth' => true, + ], //admin role allowed to all the things [ 'role' => 'admin', diff --git a/config/routes.php b/config/routes.php index f19f356a3..8c8b889ba 100644 --- a/config/routes.php +++ b/config/routes.php @@ -9,18 +9,14 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ use Cake\Core\Configure; +use Cake\Routing\RouteBuilder; use Cake\Routing\Router; +use CakeDC\Users\Middleware\SocialAuthMiddleware; -Router::plugin('CakeDC/Users', ['path' => '/users'], function ($routes) { +Router::plugin('CakeDC/Users', ['path' => '/users'], function (RouteBuilder $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', diff --git a/config/users.php b/config/users.php index 52bba11e8..44b97f7db 100644 --- a/config/users.php +++ b/config/users.php @@ -127,30 +127,57 @@ ], // 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 + 'AuthenticationComponent' => [ + 'loginAction' => '/login', + 'logoutRedirect' => '/login', + 'loginRedirect' => '/', + 'requireIdentity' => false ], - 'authenticate' => [ - 'all' => [ - 'finder' => 'auth', + 'Authenticators' => [ + 'Authentication.Session' => [ + 'skipGoogleVerify' => true, + 'sessionKey' => 'Auth', + ], + 'CakeDC/Users.Form' => [ + 'loginUrl' => '/login' + ], + 'Authentication.Token' => [ + 'skipGoogleVerify' => true, + 'header' => null, + 'queryParam' => 'api_key', + 'tokenPrefix' => null, + ], + 'CakeDC/Users.Cookie' => [ + 'skipGoogleVerify' => true, + 'rememberMeField' => 'remember_me', + 'cookie' => [ + 'expires' => '1 month', + 'httpOnly' => true, + ], + 'loginUrl' => '/login' ], - 'CakeDC/Auth.ApiKey', - 'CakeDC/Auth.RememberMe', - 'Form', ], - 'authorize' => [ - 'CakeDC/Auth.Superuser', - 'CakeDC/Auth.SimpleRbac', + 'Identifiers' => [ + 'Authentication.Password', + 'Authentication.Token' => [ + 'tokenField' => 'api_token' + ] ], ], + 'SocialAuthMiddleware' => [ + 'sessionAuthKey' => 'Auth', + 'locator' => [ + 'usernameField' => 'username', + 'finder' => 'all', + ] + ], 'OAuth' => [ 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'prefix' => null], 'providers' => [ 'facebook' => [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Facebook', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', 'options' => [ 'graphApiVersion' => 'v2.8', //bio field was deprecated on >= v2.8 'redirectUri' => Router::fullBaseUrl() . '/auth/facebook', @@ -159,6 +186,9 @@ ] ], 'twitter' => [ + 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', + 'className' => 'League\OAuth1\Client\Server\Twitter', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Twitter', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/twitter', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter', @@ -166,7 +196,9 @@ ] ], 'linkedIn' => [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\LinkedIn', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\LinkedIn', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/linkedIn', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/linkedIn', @@ -174,7 +206,9 @@ ] ], 'instagram' => [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Instagram', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Instagram', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/instagram', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/instagram', @@ -182,7 +216,9 @@ ] ], 'google' => [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Google', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Google', 'options' => [ 'userFields' => ['url', 'aboutMe'], 'redirectUri' => Router::fullBaseUrl() . '/auth/google', @@ -191,7 +227,9 @@ ] ], 'amazon' => [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'Luchianenco\OAuth2\Client\Provider\Amazon', + 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Amazon', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/amazon', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/amazon', diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index 40b1bf4bd..06307e8da 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Controller; use App\Controller\AppController as BaseController; +use Cake\Core\Configure; /** * AppController for Users Plugin @@ -31,6 +32,10 @@ public function initialize() if ($this->request->getParam('_csrfToken') === false) { $this->loadComponent('Csrf'); } - $this->loadComponent('CakeDC/Users.UsersAuth'); + $this->loadComponent('Authentication.Authentication', Configure::read('Auth.AuthenticationComponent')); + + if (Configure::read('Users.GoogleAuthenticator.login')) { + $this->loadComponent('CakeDC/Users.GoogleAuthenticator'); + } } } diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index f45ef42a4..7efaf43e0 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -45,190 +45,5 @@ class UsersAuthComponent extends Component public function initialize(array $config) { parent::initialize($config); - $this->_validateConfig(); - $this->_initAuth(); - - if (Configure::read('Users.Social.login')) { - $this->_loadSocialLogin(); - } - if (Configure::read('Users.RememberMe.active')) { - $this->_loadRememberMe(); - } - - if (Configure::read('Users.GoogleAuthenticator.login')) { - $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; } } diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index b22507464..acaa87d03 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -33,7 +33,6 @@ class SocialAccountsController extends AppController public function initialize() { parent::initialize(); - $this->Auth->allow(['validateAccount', 'resendValidation']); } /** diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 28c30d588..7314b6521 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -11,10 +11,15 @@ namespace CakeDC\Users\Controller\Traits; +use Authentication\AuthenticationService; +use Authentication\Authenticator\Result; +use CakeDC\Users\Authenticator\AuthenticatorFeedbackInterface; +use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; +use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Core\Configure; use Cake\Core\Exception\Exception; @@ -34,77 +39,17 @@ trait LoginTrait use CustomUsersTableTrait; /** - * Do twitter login - * - * @return mixed - */ - public function twitterLogin() - { - $this->autoRender = false; - $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.redirectUri'), - ]); - $oauthToken = $this->request->getQuery('oauth_token'); - $oauthVerifier = $this->request->getQuery('oauth_verifier'); - if (!empty($oauthToken) && !empty($oauthVerifier)) { - $temporaryCredentials = $this->request->getSession()->read('temporary_credentials'); - $tokenCredentials = $server->getTokenCredentials($temporaryCredentials, $oauthToken, $oauthVerifier); - $user = (array)$server->getUserDetails($tokenCredentials); - $user['token'] = [ - 'accessToken' => $tokenCredentials->getIdentifier(), - 'tokenSecret' => $tokenCredentials->getSecret(), - ]; - $this->request->getSession()->write(Configure::read('Users.Key.Session.social'), $user); - try { - $user = $this->Auth->identify(); - $this->_afterIdentifyUser($user, true); - } catch (UserNotActiveException $ex) { - $exception = $ex; - } catch (AccountNotActiveException $ex) { - $exception = $ex; - } catch (MissingEmailException $ex) { - $exception = $ex; - } - - if (!empty($exception)) { - return $this->failedSocialLogin( - $exception, - $this->request->getSession()->read(Configure::read('Users.Key.Session.social')), - true - ); - } - } else { - $temporaryCredentials = $server->getTemporaryCredentials(); - $this->request->getSession()->write('temporary_credentials', $temporaryCredentials); - $url = $server->getAuthorizationUrl($temporaryCredentials); - - return $this->redirect($url); - } - } - - /** - * @param Event $event event - * @return mixed - */ - public function failedSocialLoginListener(Event $event) - { - return $this->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); - } - - /** - * @param mixed $exception exception + * @param int $error auth error * @param mixed $data data * @param bool|false $flash flash * @return mixed */ - public function failedSocialLogin($exception, $data, $flash = false) + public function failedSocialLogin($error, $data, $flash = false) { $msg = __d('CakeDC/Users', 'Issues trying to log in with your social account'); - if (isset($exception)) { - if ($exception instanceof MissingEmailException) { + switch ($error) { + case SocialAuthMiddleware::AUTH_ERROR_MISSING_EMAIL: if ($flash) { $this->Flash->success(__d('CakeDC/Users', 'Please enter your email'), ['clear' => true]); } @@ -115,19 +60,21 @@ public function failedSocialLogin($exception, $data, $flash = false) 'controller' => 'Users', 'action' => 'socialEmail' ]); - } - if ($exception instanceof UserNotActiveException) { + case SocialAuthMiddleware::AUTH_ERROR_USER_NOT_ACTIVE: $msg = __d( 'CakeDC/Users', 'Your user has not been validated yet. Please check your inbox for instructions' ); - } elseif ($exception instanceof AccountNotActiveException) { + break; + case SocialAuthMiddleware::AUTH_ERROR_ACCOUNT_NOT_ACTIVE: $msg = __d( 'CakeDC/Users', 'Your social account has not been validated yet. Please check your inbox for instructions' ); - } + break; + } + if ($flash) { $this->request->getSession()->delete(Configure::read('Users.Key.Session.social')); $this->Flash->success($msg, ['clear' => true]); @@ -140,19 +87,25 @@ public function failedSocialLogin($exception, $data, $flash = false) * Social login * * @throws NotFoundException - * @return array + * @return mixed */ public function socialLogin() { + $status = $this->request->getAttribute('socialAuthStatus'); + if ($status === SocialAuthMiddleware::AUTH_SUCCESS) { + $user = $this->request->getAttribute('identity')->getOriginalData(); + + return $this->_afterIdentifyUser($user, true); + } $socialProvider = $this->request->getParam('provider'); - $socialUser = $this->request->getSession()->read(Configure::read('Users.Key.Session.social')); - if (empty($socialProvider) && empty($socialUser)) { + if (empty($socialProvider)) { throw new NotFoundException(); } - $user = $this->Auth->user(); - return $this->_afterIdentifyUser($user, true); + $data = $this->request->getAttribute('socialRawData'); + + return $this->failedSocialLogin($status, $data); } /** @@ -162,174 +115,74 @@ public function socialLogin() */ public function login() { - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_LOGIN); - if (is_array($event->result)) { - return $this->_afterIdentifyUser($event->result); - } - if ($event->isStopped()) { - return $this->redirect($event->result); - } + $result = $this->request->getAttribute('authentication')->getResult(); - $socialLogin = $this->_isSocialLogin(); - $googleAuthenticatorLogin = $this->_isGoogleAuthenticator(); + if ($result->isValid()) { + return $this->redirect($this->Authentication->getConfig('loginRedirect')); + } - if ($this->request->is('post')) { - if (!$this->_checkReCaptcha()) { - $this->Flash->error(__d('CakeDC/Users', 'Invalid reCaptcha')); + $service = $this->request->getAttribute('authentication'); + $message = $this->_getLoginErrorMessage($service); - return; - } - $user = $this->Auth->identify(); - - return $this->_afterIdentifyUser($user, $socialLogin, $googleAuthenticatorLogin); + if (empty($message) && $this->request->is('post')) { + $message = __d('CakeDC/Users', 'Username or password is incorrect'); } + } - if (!$this->request->is('post') && !$socialLogin) { - if ($this->Auth->user()) { - if (!$this->request->getSession()->read('Users.successSocialLogin')) { - $msg = __d('CakeDC/Users', 'You are already logged in'); - $this->Flash->error($msg); - } else { - $this->request->getSession()->delete('Users.successSocialLogin'); - $this->request->getSession()->delete('Flash'); - } - $url = $this->Auth->redirectUrl(); - - return $this->redirect($url); - } + if (!empty($message)) { + $this->Flash->error($message, 'default', [], 'auth'); } } /** - * Verify for Google Authenticator - * If Google Authenticator's enabled we need to verify - * authenticated user. To avoid accidental access to - * other URL's we store auth'ed used into temporary session - * to perform code verification. + * Get the list of login error message map by status * - * @return mixed + * @return array */ - public function verify() + protected function _getLoginErrorMessageMap() { - if (!Configure::read('Users.GoogleAuthenticator.login')) { - $message = __d('CakeDC/Users', 'Please enable Google Authenticator first.'); - $this->Flash->error($message, 'default', [], 'auth'); - - return $this->redirect(Configure::read('Auth.loginAction')); - } - - // storing user's session in the temporary one - // until the GA verification is checked - $temporarySession = $this->Auth->user(); - $this->request->getSession()->delete('Auth.User'); - - if (!empty($temporarySession)) { - $this->request->getSession()->write('temporarySession', $temporarySession); - } - - if (array_key_exists('secret', $temporarySession)) { - $secret = $temporarySession['secret']; - } - - $secretVerified = Hash::get((array)$temporarySession, 'secret_verified'); - - // showing QR-code until shared secret is verified - if (!$secretVerified) { - if (empty($secret)) { - $secret = $this->GoogleAuthenticator->createSecret(); - - // catching sql exception in case of any sql inconsistencies - try { - $query = $this->getUsersTable()->query(); - $query->update() - ->set(['secret' => $secret]) - ->where(['id' => $temporarySession['id']]); - $query->execute(); - } catch (\Exception $e) { - $this->request->getSession()->destroy(); - $message = $e->getMessage(); - $this->Flash->error($message, 'default', [], 'auth'); - - return $this->redirect(Configure::read('Auth.loginAction')); - } - } - $secretDataUri = $this->GoogleAuthenticator->getQRCodeImageAsDataUri( - Hash::get((array)$temporarySession, 'email'), - $secret - ); - $this->set(compact('secretDataUri')); - } - - if ($this->request->is('post')) { - $codeVerified = false; - $verificationCode = $this->request->getData('code'); - $user = $this->request->getSession()->read('temporarySession'); - $entity = $this->getUsersTable()->get($user['id']); - - if (!empty($entity['secret'])) { - $codeVerified = $this->GoogleAuthenticator->verifyCode($entity['secret'], $verificationCode); - } - - if ($codeVerified) { - unset($user['secret']); - - if (!$user['secret_verified']) { - $this->getUsersTable()->query()->update() - ->set(['secret_verified' => true]) - ->where(['id' => $user['id']]) - ->execute(); - } - - $this->request->getSession()->delete('temporarySession'); - $this->request->getSession()->write('Auth.User', $user); - $url = $this->Auth->redirectUrl(); - - return $this->redirect($url); - } else { - $this->request->getSession()->destroy(); - $message = __d('CakeDC/Users', 'Verification code is invalid. Try again'); - $this->Flash->error($message, 'default', [], 'auth'); - - return $this->redirect(Configure::read('Auth.loginAction')); - } - } + return [ + FormAuthenticator::FAILURE_INVALID_RECAPTCHA => __d('CakeDC/Users', 'Invalid reCaptcha'), + Result::FAILURE_IDENTITY_NOT_FOUND => __d('CakeDC/Users', 'Username or password is incorrect') + ]; } /** - * Check reCaptcha if enabled for login + * Show the login error message based on authenticators * - * @return bool + * @param AuthenticationService $service authentication service used in request + * + * @return string */ - protected function _checkReCaptcha() + protected function _getLoginErrorMessage(AuthenticationService $service) { - if (!Configure::read('Users.reCaptcha.login')) { - return true; + $message = ''; + $errorMessages = $this->_getLoginErrorMessageMap(); + foreach ($service->authenticators() as $key => $authenticator) { + if (!$authenticator instanceof AuthenticatorFeedbackInterface) { + continue; + } + + $result = $authenticator->getLastResult(); + $status = $result ? $result->getStatus() : null; + + if ($status && isset($errorMessages[$status])) { + $message = $errorMessages[$status]; + } } - return $this->validateReCaptcha( - $this->request->getData('g-recaptcha-response'), - $this->request->clientIp() - ); + return $message; } /** * Update remember me and determine redirect url after user identified * @param array $user user data after identified * @param bool $socialLogin is social login - * @param bool $googleAuthenticatorLogin googleAuthenticatorLogin * @return array */ - protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthenticatorLogin = false) + protected function _afterIdentifyUser($user, $socialLogin = false) { if (!empty($user)) { - $this->Auth->setUser($user); - - if ($googleAuthenticatorLogin) { - $url = Configure::read('GoogleAuthenticator.verifyAction'); - - return $this->redirect($url); - } - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGIN, ['user' => $user]); if (is_array($event->result)) { return $this->redirect($event->result); @@ -355,7 +208,7 @@ protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthen */ public function logout() { - $user = (array)$this->Auth->user(); + $user = $this->request->getAttribute('identity') ?? []; $eventBefore = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_LOGOUT, ['user' => $user]); if (is_array($eventBefore->result)) { @@ -370,7 +223,7 @@ public function logout() return $this->redirect($eventAfter->result); } - return $this->redirect($this->Auth->logout()); + return $this->redirect($this->Authentication->logout()); } /** diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 1efb3a45b..d24dd83a8 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -11,7 +11,7 @@ namespace CakeDC\Users\Controller\Traits; -use CakeDC\Users\Controller\Component\UsersAuthComponent; +use Cake\Utility\Hash; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; @@ -37,9 +37,9 @@ trait PasswordManagementTrait public function changePassword() { $user = $this->getUsersTable()->newEntity(); - $id = $this->Auth->user('id'); + $id = Hash::get($this->request->getAttribute('identity') ?? [], 'User.id'); if (!empty($id)) { - $user->id = $this->Auth->user('id'); + $user->id = Hash::get($this->request->getAttribute('identity') ?? [], 'id'); $validatePassword = true; //@todo add to the documentation: list of routes used $redirect = Configure::read('Users.Profile.route'); @@ -48,12 +48,12 @@ public function changePassword() $validatePassword = false; if (!$user->id) { $this->Flash->error(__d('CakeDC/Users', 'User was not found')); - $this->redirect($this->Auth->getConfig('loginAction')); + $this->redirect($this->Authentication->getConfig('loginAction')); return; } //@todo add to the documentation: list of routes used - $redirect = $this->Auth->getConfig('loginAction'); + $redirect = $this->Authentication->getConfig('loginAction'); } $this->set('validatePassword', $validatePassword); if ($this->request->is('post')) { diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index db61724d3..d6b72be24 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -31,7 +31,7 @@ trait ProfileTrait */ public function profile($id = null) { - $loggedUserId = $this->Auth->user('id'); + $loggedUserId = Hash::get($this->request->getAttribute('identity') ?? [], 'id'); $isCurrentUser = false; if (!Configure::read('Users.Profile.viewOthers') || empty($id)) { $id = $loggedUserId; diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index fc29ef602..e482ddfb1 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller\Traits; +use Cake\Utility\Hash; use CakeDC\Users\Controller\Component\UsersAuthComponent; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; @@ -38,7 +39,7 @@ public function register() throw new NotFoundException(); } - $userId = $this->Auth->user('id'); + $userId = Hash::get($this->request->getAttribute('identity') ?? [], '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')); diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index f019f9e1d..7d75b55e1 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -13,6 +13,7 @@ use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; +use CakeDC\Users\Middleware\SocialAuthMiddleware; /** * Covers registration features and email token validation @@ -29,21 +30,20 @@ trait SocialTrait */ public function socialEmail() { - if (!$this->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) { + $status = $this->request->getAttribute('socialAuthStatus'); + if ($status === SocialAuthMiddleware::AUTH_ERROR_INVALID_RECAPTCHA) { $this->Flash->error(__d('CakeDC/Users', 'The reCaptcha could not be validated')); return; } - $user = $this->Auth->identify(); - return $this->_afterIdentifyUser($user, true); + $result = $this->request->getAttribute('authentication')->getResult(); + if ($result->isValid()) { + $user = $this->request->getAttribute('identity')->getOriginalData(); + + return $this->_afterIdentifyUser($user, true); + } } } } diff --git a/src/Http/BaseApplication.php b/src/Http/BaseApplication.php new file mode 100644 index 000000000..8c3cb141c --- /dev/null +++ b/src/Http/BaseApplication.php @@ -0,0 +1,103 @@ + $options) { + if (is_numeric($identifier)) { + $identifier = $options; + $options = []; + } + + $service->loadIdentifier($identifier, $options); + } + + foreach($authenticators as $authenticator => $options) { + if (is_numeric($authenticator)) { + $authenticator = $options; + $options = []; + } + + $service->loadAuthenticator($authenticator, $options); + } + + if (Configure::read('Users.GoogleAuthenticator.login')) { + $service->loadAuthenticator('CakeDC/Users.GoogleTwoFactor', [ + 'skipGoogleVerify' => true, + ]); + } + + return $service; + } + + /** + * Setup the middleware queue your application will use. + * + * @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to setup. + * @return \Cake\Http\MiddlewareQueue The updated middleware queue. + */ + public function middleware($middlewareQueue) + { + $middlewareQueue + // Catch any exceptions in the lower layers, + // and make an error page/response + ->add(ErrorHandlerMiddleware::class) + + // Handle plugin/theme assets like CakePHP normally does. + ->add(AssetMiddleware::class) + + // Add routing middleware. + ->add(new RoutingMiddleware($this)); + + if (Configure::read('Users.Social.login')) { + $middlewareQueue + ->add(SocialAuthMiddleware::class) + ->add(SocialEmailMiddleware::class); + } + + $authentication = new AuthenticationMiddleware($this); + $middlewareQueue->add($authentication); + if (Configure::read('Users.GoogleAuthenticator.login')) { + $middlewareQueue->add('CakeDC\Users\Middleware\GoogleAuthenticatorMiddleware'); + } + + $middlewareQueue->add(new RbacMiddleware(null, [ + 'unauthorizedRedirect' => [ + 'prefix' => false, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + ] + ])); + + return $middlewareQueue; + } +} \ No newline at end of file diff --git a/src/Listener/AuthListener.php b/src/Listener/AuthListener.php new file mode 100644 index 000000000..499969730 --- /dev/null +++ b/src/Listener/AuthListener.php @@ -0,0 +1,22 @@ +loadComponent('Flash'); - // $this->loadComponent('CakeDC/Users.UsersAuth'); $this->loadComponent('RequestHandler'); } } From 5756788442aad32a0338796ca0e5e8ba91af1efa Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 May 2018 17:52:08 -0300 Subject: [PATCH 013/685] removed invalid code --- src/Controller/Traits/LoginTrait.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 7314b6521..4aa881523 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -129,11 +129,6 @@ public function login() } } - if (!empty($message)) { - $this->Flash->error($message, 'default', [], 'auth'); - } - } - /** * Get the list of login error message map by status * From 0e506bce7e0c7f03b14fd65c5ab97b3fc9736fbc Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 May 2018 18:01:03 -0300 Subject: [PATCH 014/685] Using _afterIdentifyUser on log-in --- src/Controller/Traits/LoginTrait.php | 38 ++++++++-------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 4aa881523..6fd545748 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -118,7 +118,9 @@ public function login() $result = $this->request->getAttribute('authentication')->getResult(); if ($result->isValid()) { - return $this->redirect($this->Authentication->getConfig('loginRedirect')); + $user = $this->request->getAttribute('identity')->getOriginalData(); + + return $this->_afterIdentifyUser($user, false); } $service = $this->request->getAttribute('authentication'); @@ -127,6 +129,10 @@ public function login() if (empty($message) && $this->request->is('post')) { $message = __d('CakeDC/Users', 'Username or password is incorrect'); } + + if ($message) { + $this->Flash->error($message, 'default', [], 'auth'); + } } /** @@ -170,7 +176,8 @@ protected function _getLoginErrorMessage(AuthenticationService $service) } /** - * Update remember me and determine redirect url after user identified + * Determine redirect url after user identified + * * @param array $user user data after identified * @param bool $socialLogin is social login * @return array @@ -183,16 +190,14 @@ protected function _afterIdentifyUser($user, $socialLogin = false) return $this->redirect($event->result); } - $url = $this->Auth->redirectUrl(); - - return $this->redirect($url); + return $this->redirect($this->Authentication->getConfig('loginRedirect')); } else { if (!$socialLogin) { $message = __d('CakeDC/Users', 'Username or password is incorrect'); $this->Flash->error($message, 'default', [], 'auth'); } - return $this->redirect(Configure::read('Auth.loginAction')); + return $this->redirect($this->Authentication->getConfig('loginAction')); } } @@ -220,25 +225,4 @@ public function logout() return $this->redirect($this->Authentication->logout()); } - - /** - * Check if we are doing a social login - * - * @return bool true if social login is enabled and we are processing the social login - * data in the request - */ - protected function _isSocialLogin() - { - return Configure::read('Users.Social.login') && - $this->request->getSession()->check(Configure::read('Users.Key.Session.social')); - } - - /** - * Check if we doing Google Authenticator Two Factor auth - * @return bool true if Google Authenticator is enabled - */ - protected function _isGoogleAuthenticator() - { - return Configure::read('Users.GoogleAuthenticator.login'); - } } From a7649bf33976f2a3aa42eb4445e6151af11ba3a0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 May 2018 18:03:41 -0300 Subject: [PATCH 015/685] Remove old social authenticate, now we use social layer --- src/Auth/SocialAuthenticate.php | 488 -------------------------------- 1 file changed, 488 deletions(-) delete mode 100755 src/Auth/SocialAuthenticate.php 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; - } -} From 27ceb556884581f5dd91ad18513624e763c4630d Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 May 2018 18:47:17 -0300 Subject: [PATCH 016/685] setup plugin object class --- src/Plugin.php | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/Plugin.php diff --git a/src/Plugin.php b/src/Plugin.php new file mode 100644 index 000000000..51c0a980a --- /dev/null +++ b/src/Plugin.php @@ -0,0 +1,80 @@ + $options) { + if (is_numeric($identifier)) { + $identifier = $options; + $options = []; + } + + $service->loadIdentifier($identifier, $options); + } + + foreach($authenticators as $authenticator => $options) { + if (is_numeric($authenticator)) { + $authenticator = $options; + $options = []; + } + + $service->loadAuthenticator($authenticator, $options); + } + + if (Configure::read('Users.GoogleAuthenticator.login')) { + $service->loadAuthenticator('CakeDC/Users.GoogleTwoFactor', [ + 'skipGoogleVerify' => true, + ]); + } + + return $service; + } + + /** + * {@inheritdoc} + */ + public function middleware($middlewareQueue) + { + if (Configure::read('Users.Social.login')) { + $middlewareQueue + ->add(SocialAuthMiddleware::class) + ->add(SocialEmailMiddleware::class); + } + + $authentication = new AuthenticationMiddleware($this); + $middlewareQueue->add($authentication); + if (Configure::read('Users.GoogleAuthenticator.login')) { + $middlewareQueue->add('CakeDC\Users\Middleware\GoogleAuthenticatorMiddleware'); + } + + $middlewareQueue->add(new RbacMiddleware(null, [ + 'unauthorizedRedirect' => [ + 'prefix' => false, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + ] + ])); + + return $middlewareQueue; + } +} \ No newline at end of file From 8779917d4e7cc24c5f83dc8cea3758d7180d8d14 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 25 May 2018 08:18:27 +0200 Subject: [PATCH 017/685] Fix issue with null token in AbstractMapper refs #657 --- src/Auth/Social/Mapper/AbstractMapper.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Auth/Social/Mapper/AbstractMapper.php b/src/Auth/Social/Mapper/AbstractMapper.php index e6e44d28f..3cbe6e69b 100644 --- a/src/Auth/Social/Mapper/AbstractMapper.php +++ b/src/Auth/Social/Mapper/AbstractMapper.php @@ -102,7 +102,11 @@ protected function _map() } $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, From ea0b8b971b074995790ab34e4eef6b500eb5b3bb Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 29 May 2018 11:03:57 +0200 Subject: [PATCH 018/685] fix phpcs --- src/Auth/Social/Mapper/Tumblr.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Auth/Social/Mapper/Tumblr.php b/src/Auth/Social/Mapper/Tumblr.php index f5e4867ea..2f18418a8 100644 --- a/src/Auth/Social/Mapper/Tumblr.php +++ b/src/Auth/Social/Mapper/Tumblr.php @@ -36,7 +36,6 @@ class Tumblr extends AbstractMapper 'link' => 'extra.blogs.0.url' ]; - /** * @return string */ From 3cf87b4f5aa40659e1f9886857bbf40a6f284ec9 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 8 Jun 2018 15:56:08 -0300 Subject: [PATCH 019/685] Save user in temp session for Two factor authentication --- src/Controller/Traits/LoginTrait.php | 14 ++-- .../Controller/Traits/LoginTraitTest.php | 66 +++++++++++-------- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 28c30d588..8ac463207 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -218,14 +218,7 @@ public function verify() return $this->redirect(Configure::read('Auth.loginAction')); } - // storing user's session in the temporary one - // until the GA verification is checked - $temporarySession = $this->Auth->user(); - $this->request->getSession()->delete('Auth.User'); - - if (!empty($temporarySession)) { - $this->request->getSession()->write('temporarySession', $temporarySession); - } + $temporarySession = $this->request->getSession()->read('temporarySession'); if (array_key_exists('secret', $temporarySession)) { $secret = $temporarySession['secret']; @@ -322,14 +315,17 @@ protected function _checkReCaptcha() protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthenticatorLogin = false) { if (!empty($user)) { - $this->Auth->setUser($user); if ($googleAuthenticatorLogin) { + // storing user's session in the temporary one + // until the GA verification is checked + $this->request->getSession()->write('temporarySession', $user); $url = Configure::read('GoogleAuthenticator.verifyAction'); return $this->redirect($url); } + $this->Auth->setUser($user); $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGIN, ['user' => $user]); if (is_array($event->result)) { return $this->redirect($event->result); diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 47a3d29c5..26e739d38 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -391,24 +391,21 @@ public function testFailedSocialUserAccount() public function testVerifyHappy() { Configure::write('Users.GoogleAuthenticator.login', true); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', ]) - ->disableOriginalConstructor() - ->getMock(); - $user = [ - 'id' => 1, - 'secret_verified' => 1, - ]; - $this->Trait->Auth->expects($this->at(0)) - ->method('user') - ->will($this->returnValue($user)); + $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is', 'getData', 'allow']) + ->setMethods(['is', 'getData', 'allow', 'getSession']) ->getMock(); - $this->Trait->request->expects($this->at(0)) + $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(); } @@ -433,30 +430,26 @@ public function testVerifyNotEnabled() public function testVerifyGetShowQR() { Configure::write('Users.GoogleAuthenticator.login', true); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', ]) - ->disableOriginalConstructor() - ->getMock(); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'email' => 'email@example.com', - 'secret_verified' => 0, - ]; - $this->Trait->Auth->expects($this->at(0)) - ->method('user') - ->will($this->returnValue($user)); + $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) ->disableOriginalConstructor() ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) ->getMock(); $this->Trait->request = $this->getMockBuilder(ServerRequest::class) - ->setMethods(['is', 'getData', 'allow']) + ->setMethods(['is', 'getData', 'allow', 'getSession']) ->getMock(); - $this->Trait->request->expects($this->at(0)) + $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')); @@ -469,4 +462,23 @@ public function testVerifyGetShowQR() ->with(['secretDataUri' => 'newDataUriGenerated']); $this->Trait->verify(); } + + /** + * 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('getSession') + ->willReturn($session); + } } From 03c6fb277d28ba43c4dd51bb6ad82f118338c52f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 8 Jun 2018 16:10:48 -0300 Subject: [PATCH 020/685] Save user in temp session for Two factor authentication --- src/Controller/Traits/LoginTrait.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 8ac463207..7c3d516af 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -315,7 +315,6 @@ protected function _checkReCaptcha() protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthenticatorLogin = false) { if (!empty($user)) { - if ($googleAuthenticatorLogin) { // storing user's session in the temporary one // until the GA verification is checked From c56d6fc1dcedf6327f0a211982021892908c1463 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 8 Jun 2018 16:21:43 -0300 Subject: [PATCH 021/685] Two factor authentication verify should work when temporary session is present --- src/Controller/Traits/LoginTrait.php | 5 +++++ .../Controller/Traits/LoginTraitTest.php | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 7c3d516af..796f561a9 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -219,6 +219,11 @@ public function verify() } $temporarySession = $this->request->getSession()->read('temporarySession'); + if (empty($temporarySession)) { + $this->Flash->error(__d('CakeDC/Users', 'Invalid request.'), 'default', [], 'auth'); + + return $this->redirect(Configure::read('Auth.loginAction')); + } if (array_key_exists('secret', $temporarySession)) { $secret = $temporarySession['secret']; diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 26e739d38..81571fc5e 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -409,6 +409,28 @@ public function testVerifyHappy() $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->verify(); + } + /** * testVerifyHappy * From c17ac3a0a29263b3aedfc8c7429c763fe794c310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 11 Jun 2018 10:00:35 +0100 Subject: [PATCH 022/685] check for array when extracting temporarySession --- src/Controller/Traits/LoginTrait.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 796f561a9..471bc4b39 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -219,17 +219,14 @@ public function verify() } $temporarySession = $this->request->getSession()->read('temporarySession'); - if (empty($temporarySession)) { + if (!is_array($temporarySession) || empty($temporarySession)) { $this->Flash->error(__d('CakeDC/Users', 'Invalid request.'), 'default', [], 'auth'); return $this->redirect(Configure::read('Auth.loginAction')); } - if (array_key_exists('secret', $temporarySession)) { - $secret = $temporarySession['secret']; - } - - $secretVerified = Hash::get((array)$temporarySession, 'secret_verified'); + $secret = Hash::get($temporarySession, 'secret'); + $secretVerified = Hash::get($temporarySession, 'secret_verified'); // showing QR-code until shared secret is verified if (!$secretVerified) { From d218b9a0a0070eed960ec89650aba5d91da21c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 11 Jun 2018 11:07:07 +0100 Subject: [PATCH 023/685] refs #rochamarcelo-google-two-factor-auth fix deprecations --- .../Controller/Component/GoogleAuthenticatorComponentTest.php | 1 - tests/TestCase/Controller/Component/UsersAuthComponentTest.php | 1 - tests/TestCase/Controller/Traits/RegisterTraitTest.php | 2 -- tests/TestCase/Model/Table/UsersTableTest.php | 1 - tests/TestCase/View/Helper/UserHelperTest.php | 1 - 5 files changed, 6 deletions(-) diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index f708e7f6f..c1e665b55 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -44,7 +44,6 @@ public function setUp() $this->backupUsersConfig = Configure::read('Users'); Router::reload(); - Plugin::routes('CakeDC/Users'); Router::connect('/route/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 922646bda..7860d3439 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -53,7 +53,6 @@ public function setUp() $this->backupUsersConfig = Configure::read('Users'); Router::reload(); - Plugin::routes('CakeDC/Users'); Router::connect('/route/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index ec2a005d9..6050b9bda 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -31,8 +31,6 @@ public function setUp() $this->traitMockMethods = ['validate', 'dispatchEvent', 'set', 'validateReCaptcha', 'redirect']; $this->mockDefaultEmail = true; parent::setUp(); - - Plugin::routes('CakeDC/Users'); } /** diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index dcad61b07..03b91b37e 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -56,7 +56,6 @@ public function setUp() 'transport' => 'test', 'from' => 'cakedc@example.com' ]); - Plugin::routes('CakeDC/Users'); } /** diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index e20b30e77..f0bf717f0 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -57,7 +57,6 @@ public function setUp() } parent::setUp(); - Plugin::routes('CakeDC/Users'); $this->View = $this->getMockBuilder('Cake\View\View') ->setMethods(['append']) ->getMock(); From efe42973cd1d17780fd986301f2c8c40db38429e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 13 Jun 2018 14:07:49 +0100 Subject: [PATCH 024/685] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index d42bf6c44..0a8899195 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 7 :minor: 0 -:patch: 0 +:patch: 1 :special: '' From aba4fd1806fa6900990c478e0080bdac2517aa38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Wed, 13 Jun 2018 14:11:43 +0100 Subject: [PATCH 025/685] refs #692 update cakedc/auth --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 93d1a1dbd..618b9dba8 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ }, "require": { "cakephp/cakephp": "^3.6", - "cakedc/auth": "^2.0" + "cakedc/auth": "^3.0" }, "require-dev": { "phpunit/phpunit": "^5.0", From de13b7efd2ffa43dd16487d01927353dcc9bf391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 13 Jun 2018 14:16:58 +0100 Subject: [PATCH 026/685] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ce6ea612..be1b47fca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ Changelog Releases for CakePHP 3 ------------- +* 7.0.1 + * Fixed a security issue in 2 factor authentication, reported by @ndm + * 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` From b1e5dee784e81989a0edd7d8f23db22bf00ebfd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 13 Jun 2018 14:21:22 +0100 Subject: [PATCH 027/685] fix typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be1b47fca..05bfe9836 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ Releases for CakePHP 3 ------------- * 7.0.1 - * Fixed a security issue in 2 factor authentication, reported by @ndm + * Fixed a security issue in 2 factor authentication, reported by @ndm2 * Updated to cakedc/auth ^3.0 * Documentation fixes From 9b85908d4648fe13d5225f01b487d192208a644b Mon Sep 17 00:00:00 2001 From: ndm2 Date: Wed, 13 Jun 2018 21:51:55 +0200 Subject: [PATCH 028/685] Fix secrets being regenerated on every request. This patch ensures that a new secret is only generated in case the user record doesn't already has a secret set. --- src/Controller/Traits/LoginTrait.php | 2 + .../Controller/Traits/LoginTraitTest.php | 116 +++++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 471bc4b39..3e6fa32f0 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -240,6 +240,8 @@ public function verify() ->set(['secret' => $secret]) ->where(['id' => $temporarySession['id']]); $query->execute(); + + $this->request->getSession()->write('temporarySession.secret', $secret); } catch (\Exception $e) { $this->request->getSession()->destroy(); $message = $e->getMessage(); diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 81571fc5e..1f1f24901 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -485,10 +485,122 @@ public function testVerifyGetShowQR() $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() + ); + } + /** * Mock session and mock session attributes * - * @return void + * @return \Cake\Http\Session */ protected function _mockSession($attributes) { @@ -502,5 +614,7 @@ protected function _mockSession($attributes) ->expects($this->any()) ->method('getSession') ->willReturn($session); + + return $session; } } From 0f26b675fde34bce05278614c817daafc2dc018c Mon Sep 17 00:00:00 2001 From: ndm2 Date: Wed, 13 Jun 2018 21:56:44 +0200 Subject: [PATCH 029/685] Use the Auth component to store user data. Ensures that the user data is persisted in the storage configured for the Auth component, and that the `secret_verified` flag is set properly. --- src/Controller/Traits/LoginTrait.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 3e6fa32f0..1a50890d2 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -275,10 +275,12 @@ public function verify() ->set(['secret_verified' => true]) ->where(['id' => $user['id']]) ->execute(); + + $user['secret_verified'] = true; } $this->request->getSession()->delete('temporarySession'); - $this->request->getSession()->write('Auth.User', $user); + $this->Auth->setUser($user); $url = $this->Auth->redirectUrl(); return $this->redirect($url); From c2f04910d55ad3f98c2f2af9d93f49b484d5a042 Mon Sep 17 00:00:00 2001 From: ndm2 Date: Wed, 13 Jun 2018 22:01:56 +0200 Subject: [PATCH 030/685] Add two-step auth code verification tests. --- .../Controller/Traits/LoginTraitTest.php | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 1f1f24901..fae331d7f 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -597,6 +597,181 @@ public function testVerifyGetDoesNotGenerateNewSecret() ); } + /** + * Tests that posting a valid code causes verification to succeed. + */ + public function testVerifyPostValidCode() + { + 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', '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 * From 526d066320a915c7e64817392ad02335e2e8d3a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 20 Jun 2018 09:48:55 +0100 Subject: [PATCH 031/685] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index 0a8899195..ae45234e5 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 7 :minor: 0 -:patch: 1 +:patch: 2 :special: '' From 2fc40f28c051950a3c9b44a26a2d3b837d954045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 20 Jun 2018 09:49:28 +0100 Subject: [PATCH 032/685] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05bfe9836..b96bd7d4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ Changelog Releases for CakePHP 3 ------------- +* 7.0.1 + * 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 From 8582034b91e5d5ba1c28031b7e1aeaf3d31c6b4d Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Jun 2018 11:09:59 -0300 Subject: [PATCH 033/685] Removed tests from removed classes --- .../TestCase/Auth/SocialAuthenticateTest.php | 644 ------------------ .../Component/UsersAuthComponentTest.php | 516 -------------- 2 files changed, 1160 deletions(-) delete mode 100644 tests/TestCase/Auth/SocialAuthenticateTest.php delete mode 100644 tests/TestCase/Controller/Component/UsersAuthComponentTest.php 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/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php deleted file mode 100644 index 922646bda..000000000 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ /dev/null @@ -1,516 +0,0 @@ -backupUsersConfig = Configure::read('Users'); - - Router::reload(); - Plugin::routes('CakeDC/Users'); - 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); - } -} From 64bee07f59da9e476d432d7169e79cc1f29df109 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Jun 2018 11:10:29 -0300 Subject: [PATCH 034/685] Fixing login unit tests --- .../Controller/Traits/BaseTraitTest.php | 52 +++++++++ .../Controller/Traits/LoginTraitTest.php | 102 +++--------------- 2 files changed, 69 insertions(+), 85 deletions(-) diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 201e7a3bc..90186a914 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -11,7 +11,12 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; +use Authentication\AuthenticationService; +use Authentication\Authenticator\Result; +use Authentication\Controller\Component\AuthenticationComponent; use Authentication\Identity; +use Cake\Controller\ComponentRegistry; +use Cake\Controller\Controller; use Cake\Event\Event; use Cake\Mailer\Email; use Cake\ORM\Entity; @@ -40,6 +45,8 @@ abstract class BaseTraitTest extends TestCase public $traitMockMethods = []; public $mockDefaultEmail = false; + public $successLoginRedirect = '/home'; + /** * SetUp and create Trait * @@ -215,6 +222,51 @@ protected function _mockAuth() ->getMock(); } + /** + * Mock the Authentication service + * + * @param array $user + * @return void + */ + protected function _mockAuthentication($user = null) + { + $config = [ + 'identifiers' => [ + 'Authentication.Password' + ], + 'authenticators' => [ + 'Authentication.Session', + 'Authentication.Form' + ] + ]; + $authentication = $this->getMockBuilder(AuthenticationService::class)->setConstructorArgs([$config])->setMethods([ + 'getResult' + ])->getMock(); + + if ($user) { + $user = new User($user); + $identity = new Identity($user); + $result = new Result($user, Result::SUCCESS); + $this->Trait->request = $this->Trait->request->withAttribute('identity', $identity); + } else { + $result = new Result($user, Result::FAILURE_CREDENTIALS_MISSING); + } + + $authentication->expects($this->any()) + ->method('getResult') + ->will($this->returnValue($result)); + + $this->Trait->request = $this->Trait->request->withAttribute('authentication', $authentication); + + $controller = new Controller($this->Trait->request); + $registry = new ComponentRegistry($controller); + $this->Trait->Authentication = new AuthenticationComponent($registry, [ + 'loginRedirect' => $this->successLoginRedirect + ]);; + } + + + /** * mock utility * diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 47a3d29c5..2ae9d9732 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -76,26 +76,19 @@ public function testLoginHappy() ->method('is') ->with('post') ->will($this->returnValue(true)); - $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', 'identify', 'setUser', 'redirectUrl']) + $this->_mockAuthentication([ + 'id' => 1 + ]); + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['error']) ->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->Flash->expects($this->never()) + ->method('error'); + $this->Trait->expects($this->once()) ->method('redirect') - ->with($redirectLoginOK); + ->with($this->successLoginRedirect); $this->Trait->login(); } @@ -157,63 +150,6 @@ public function testAfterIdentifyEmptyUserSocialLogin() $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 * @@ -221,27 +157,23 @@ public function testLoginBeforeLoginReturningStoppedEvent() */ 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)) + $this->Trait->request->expects($this->once()) ->method('is') ->with('post') ->will($this->returnValue(false)); + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['error']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->Flash->expects($this->never()) + ->method('error'); + $this->_mockAuthentication(); $this->Trait->login(); - Configure::write('Users.Social.login', $socialLogin); } /** From 3b5b8f05665a6871b58ca863c903eadb00774326 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Jun 2018 13:23:29 -0300 Subject: [PATCH 035/685] Fixing traits unit tests --- src/Controller/Traits/GoogleVerifyTrait.php | 4 +- src/Controller/Traits/LoginTrait.php | 26 +-- src/Controller/Traits/SocialTrait.php | 2 +- .../Controller/Traits/BaseTraitTest.php | 7 +- .../Traits/GoogleVerifyTraitTest.php | 155 +++++++++++++ .../Controller/Traits/LoginTraitTest.php | 212 +++--------------- 6 files changed, 200 insertions(+), 206 deletions(-) create mode 100644 tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php diff --git a/src/Controller/Traits/GoogleVerifyTrait.php b/src/Controller/Traits/GoogleVerifyTrait.php index 6c1263f9c..87f09f16f 100644 --- a/src/Controller/Traits/GoogleVerifyTrait.php +++ b/src/Controller/Traits/GoogleVerifyTrait.php @@ -24,13 +24,13 @@ public function verify() $temporarySession = $this->request->getSession()->read('temporarySession'); $secretVerified = $temporarySession['secret_verified']; - // showing QR-code until shared secret is verified if (!$secretVerified) { $secret = $this->onVerifyGetSecret($temporarySession); if (empty($secret)) { return $this->redirect($loginAction); } + $secretDataUri = $this->GoogleAuthenticator->getQRCodeImageAsDataUri( $temporarySession['email'], $secret @@ -79,7 +79,7 @@ protected function isVerifyAllowed() */ protected function onVerifyGetSecret($user) { - if ($user['secret']) { + if (isset($user['secret']) && $user['secret']) { return $user['secret']; } diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 6fd545748..c3f2f55ba 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -95,7 +95,7 @@ public function socialLogin() if ($status === SocialAuthMiddleware::AUTH_SUCCESS) { $user = $this->request->getAttribute('identity')->getOriginalData(); - return $this->_afterIdentifyUser($user, true); + return $this->_afterIdentifyUser($user); } $socialProvider = $this->request->getParam('provider'); @@ -120,7 +120,7 @@ public function login() if ($result->isValid()) { $user = $this->request->getAttribute('identity')->getOriginalData(); - return $this->_afterIdentifyUser($user, false); + return $this->_afterIdentifyUser($user); } $service = $this->request->getAttribute('authentication'); @@ -179,26 +179,16 @@ protected function _getLoginErrorMessage(AuthenticationService $service) * Determine redirect url after user identified * * @param array $user user data after identified - * @param bool $socialLogin is social login * @return array */ - protected function _afterIdentifyUser($user, $socialLogin = false) + protected function _afterIdentifyUser($user) { - if (!empty($user)) { - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGIN, ['user' => $user]); - if (is_array($event->result)) { - return $this->redirect($event->result); - } - - return $this->redirect($this->Authentication->getConfig('loginRedirect')); - } else { - if (!$socialLogin) { - $message = __d('CakeDC/Users', 'Username or password is incorrect'); - $this->Flash->error($message, 'default', [], 'auth'); - } - - return $this->redirect($this->Authentication->getConfig('loginAction')); + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGIN, ['user' => $user]); + if (is_array($event->result)) { + return $this->redirect($event->result); } + + return $this->redirect($this->Authentication->getConfig('loginRedirect')); } /** diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 7d75b55e1..5d4937a10 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -42,7 +42,7 @@ public function socialEmail() if ($result->isValid()) { $user = $this->request->getAttribute('identity')->getOriginalData(); - return $this->_afterIdentifyUser($user, true); + return $this->_afterIdentifyUser($user); } } } diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 90186a914..3fd35a6c3 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -47,6 +47,8 @@ abstract class BaseTraitTest extends TestCase public $successLoginRedirect = '/home'; + public $logoutRedirect = '/login?fromlogout=1'; + /** * SetUp and create Trait * @@ -113,7 +115,7 @@ protected function _mockSession($attributes) $this->Trait->request ->expects($this->any()) - ->method('session') + ->method('getSession') ->willReturn($session); } @@ -261,7 +263,8 @@ protected function _mockAuthentication($user = null) $controller = new Controller($this->Trait->request); $registry = new ComponentRegistry($controller); $this->Trait->Authentication = new AuthenticationComponent($registry, [ - 'loginRedirect' => $this->successLoginRedirect + 'loginRedirect' => $this->successLoginRedirect, + 'logoutRedirect' => $this->logoutRedirect ]);; } diff --git a/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php b/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php new file mode 100644 index 000000000..278369c2a --- /dev/null +++ b/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php @@ -0,0 +1,155 @@ +traitClassName = 'CakeDC\Users\Controller\Traits\GoogleVerifyTrait'; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; + + parent::setUp(); + $request = new ServerRequest(); + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\GoogleVerifyTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', 'getUsersTable']) + ->getMockForTrait(); + + $this->Trait->request = $request; + Configure::write('Auth.AuthenticationComponent.loginAction', $this->loginPage); + } + + /** + * tearDown + * + * @return void + */ + public function tearDown() + { + parent::tearDown(); + } + + /** + * 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->Trait->expects($this->never()) + ->method('redirect'); + + $this->_mockSession([ + 'temporarySession' => [ + 'id' => 1, + 'secret_verified' => 1, + ] + ]); + + $this->Trait->verify(); + } + + /** + * testVerifyHappy + * + */ + public function testVerifyNotEnabled() + { + $loginAction = Configure::read('Auth.AuthenticationComponent.loginAction'); + $this->_mockFlash(); + Configure::write('Users.GoogleAuthenticator.login', false); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Please enable Google Authenticator first.'); + $this->Trait->expects($this->once()) + ->method('redirect') + ->with($this->loginPage); + + $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->_mockSession([ + 'temporarySession' => [ + 'id' => '00000000-0000-0000-0000-000000000001', + 'email' => 'email@example.com', + 'secret_verified' => 0, + ] + ]); + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue(TableRegistry::getTableLocator()->get('CakeDC/Users.Users'))); + + $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')); + $this->Trait->expects($this->once()) + ->method('set') + ->with(['secretDataUri' => 'newDataUriGenerated']); + + $this->Trait->verify(); + $user = $this->Trait->getUsersTable()->findById('00000000-0000-0000-0000-000000000001')->firstOrFail(); + $this->assertEquals('newSecret', $user->secret); + } +} diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 2ae9d9732..9b110a848 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -24,6 +24,7 @@ use Cake\Network\Request; use Cake\ORM\Entity; use Cake\TestSuite\TestCase; +use CakeDC\Users\Middleware\SocialAuthMiddleware; class LoginTraitTest extends BaseTraitTest { @@ -92,64 +93,6 @@ public function testLoginHappy() $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->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 * @@ -157,7 +100,6 @@ public function testAfterIdentifyEmptyUserSocialLogin() */ public function testLoginGet() { - Configure::write('Users.Social.login', false); $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') ->setMethods(['is']) ->disableOriginalConstructor() @@ -172,6 +114,10 @@ public function testLoginGet() ->getMock(); $this->Trait->Flash->expects($this->never()) ->method('error'); + + $this->Trait->expects($this->never()) + ->method('redirect'); + $this->_mockAuthentication(); $this->Trait->login(); } @@ -188,13 +134,12 @@ public function testLogout() ->setMethods(['logout', 'user']) ->disableOriginalConstructor() ->getMock(); - $redirectLogoutOK = '/'; - $this->Trait->Auth->expects($this->once()) - ->method('logout') - ->will($this->returnValue($redirectLogoutOK)); + $this->_mockAuthentication([ + 'id' => 1 + ]); $this->Trait->expects($this->once()) ->method('redirect') - ->with($redirectLogoutOK); + ->with($this->logoutRedirect); $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') ->setMethods(['success']) ->disableOriginalConstructor() @@ -212,16 +157,12 @@ public function testLogout() */ public function testFailedSocialLoginMissingEmail() { - $event = new Entity(); - $event->data = [ - 'exception' => new MissingEmailException('Email not present'), - 'rawData' => [ - 'id' => 11111, - 'username' => 'user-1' - ] + $data = [ + 'id' => 11111, + 'username' => 'user-1' ]; $this->_mockFlash(); - $this->_mockRequestGet(); + $this->_mockAuthentication(); $this->Trait->Flash->expects($this->once()) ->method('success') ->with('Please enter your email'); @@ -230,7 +171,7 @@ public function testFailedSocialLoginMissingEmail() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); - $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); + $this->Trait->failedSocialLogin(SocialAuthMiddleware::AUTH_ERROR_MISSING_EMAIL, $data, true); } /** @@ -240,16 +181,12 @@ public function testFailedSocialLoginMissingEmail() */ public function testFailedSocialUserNotActive() { - $event = new Entity(); - $event->data = [ - 'exception' => new UserNotActiveException('Facebook user-1'), - 'rawData' => [ - 'id' => 111111, - 'username' => 'user-1' - ] + $data = [ + 'id' => 111111, + 'username' => 'user-1' ]; $this->_mockFlash(); - $this->_mockRequestGet(); + $this->_mockAuthentication(); $this->Trait->Flash->expects($this->once()) ->method('success') ->with('Your user has not been validated yet. Please check your inbox for instructions'); @@ -258,7 +195,7 @@ public function testFailedSocialUserNotActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); + $this->Trait->failedSocialLogin(SocialAuthMiddleware::AUTH_ERROR_USER_NOT_ACTIVE, $data, true); } /** @@ -269,15 +206,12 @@ public function testFailedSocialUserNotActive() public function testFailedSocialUserAccountNotActive() { $event = new Entity(); - $event->data = [ - 'exception' => new AccountNotActiveException('Facebook user-1'), - 'rawData' => [ - 'id' => 111111, - 'username' => 'user-1' - ] + $data = [ + 'id' => 111111, + 'username' => 'user-1' ]; $this->_mockFlash(); - $this->_mockRequestGet(); + $this->_mockAuthentication(); $this->Trait->Flash->expects($this->once()) ->method('success') ->with('Your social account has not been validated yet. Please check your inbox for instructions'); @@ -286,7 +220,7 @@ public function testFailedSocialUserAccountNotActive() ->method('redirect') ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); + $this->Trait->failedSocialLogin(SocialAuthMiddleware::AUTH_ERROR_ACCOUNT_NOT_ACTIVE, $data, true); } /** @@ -297,14 +231,12 @@ public function testFailedSocialUserAccountNotActive() public function testFailedSocialUserAccount() { $event = new Entity(); - $event->data = [ - 'rawData' => [ - 'id' => 111111, - 'username' => 'user-1' - ] + $data = [ + 'id' => 111111, + 'username' => 'user-1' ]; $this->_mockFlash(); - $this->_mockRequestGet(); + $this->_mockAuthentication(); $this->Trait->Flash->expects($this->once()) ->method('success') ->with('Issues trying to log in with your social account'); @@ -313,92 +245,6 @@ public function testFailedSocialUserAccount() ->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->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', ]) - ->disableOriginalConstructor() - ->getMock(); - $user = [ - 'id' => 1, - 'secret_verified' => 1, - ]; - $this->Trait->Auth->expects($this->at(0)) - ->method('user') - ->will($this->returnValue($user)); - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') - ->setMethods(['is', 'getData', 'allow']) - ->getMock(); - $this->Trait->request->expects($this->at(0)) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); - $this->Trait->verify(); - } - - /** - * testVerifyHappy - * - */ - public function testVerifyNotEnabled() - { - $this->_mockFlash(); - Configure::write('Users.GoogleAuthenticator.login', false); - $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->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['user', ]) - ->disableOriginalConstructor() - ->getMock(); - $user = [ - 'id' => '00000000-0000-0000-0000-000000000001', - 'email' => 'email@example.com', - 'secret_verified' => 0, - ]; - $this->Trait->Auth->expects($this->at(0)) - ->method('user') - ->will($this->returnValue($user)); - $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) - ->disableOriginalConstructor() - ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) - ->getMock(); - - $this->Trait->request = $this->getMockBuilder(ServerRequest::class) - ->setMethods(['is', 'getData', 'allow']) - ->getMock(); - $this->Trait->request->expects($this->at(0)) - ->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')); - $this->Trait->expects($this->at(0)) - ->method('set') - ->with(['secretDataUri' => 'newDataUriGenerated']); - $this->Trait->verify(); + $this->Trait->failedSocialLogin(null, $data, true); } } From a12791a273ea88d0791280ee4521ecbde60383a3 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Jun 2018 13:51:07 -0300 Subject: [PATCH 036/685] Removing reference of Auth component and update tests --- .../Traits/PasswordManagementTrait.php | 9 +++- src/Listener/AuthListener.php | 2 + src/Plugin.php | 1 + .../Controller/Traits/BaseTraitTest.php | 47 +++---------------- .../Controller/Traits/LinkSocialTraitTest.php | 10 ++-- .../Traits/PasswordManagementTraitTest.php | 4 +- .../Controller/Traits/ProfileTraitTest.php | 4 +- .../Controller/Traits/RegisterTraitTest.php | 18 +++---- 8 files changed, 34 insertions(+), 61 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index d24dd83a8..b093b0663 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -18,6 +18,8 @@ use Cake\Core\Configure; use Cake\Log\Log; use Cake\Validation\Validator; +use CakeDC\Users\Listener\AuthListener; +use CakeDC\Users\Plugin; use Exception; /** @@ -37,7 +39,8 @@ trait PasswordManagementTrait public function changePassword() { $user = $this->getUsersTable()->newEntity(); - $id = Hash::get($this->request->getAttribute('identity') ?? [], 'User.id'); + $id = Hash::get($this->request->getAttribute('identity') ?? [], 'id'); + if (!empty($id)) { $user->id = Hash::get($this->request->getAttribute('identity') ?? [], 'id'); $validatePassword = true; @@ -67,12 +70,14 @@ public function changePassword() $this->request->getData(), ['validate' => $validator] ); + if ($user->getErrors()) { $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); } else { $user = $this->getUsersTable()->changePassword($user); + if ($user) { - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_CHANGE_PASSWORD, ['user' => $user]); + $event = $this->dispatchEvent(Plugin::EVENT_AFTER_CHANGE_PASSWORD, ['user' => $user]); if (!empty($event) && is_array($event->result)) { return $this->redirect($event->result); } diff --git a/src/Listener/AuthListener.php b/src/Listener/AuthListener.php index 499969730..e25c13674 100644 --- a/src/Listener/AuthListener.php +++ b/src/Listener/AuthListener.php @@ -10,6 +10,8 @@ class AuthListener implements EventListenerInterface const EVENT_AFTER_SOCIAL_REGISTER = 'Users.SocialAuth.afterRegister'; + + /** * All implemented events are declared * diff --git a/src/Plugin.php b/src/Plugin.php index 51c0a980a..eb36a2922 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -11,6 +11,7 @@ class Plugin extends BasePlugin { + const EVENT_AFTER_CHANGE_PASSWORD = 'Users.Managment.afterResetPassword'; /** * load authenticators and identifiers * diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 3fd35a6c3..4fb947ffc 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -49,6 +49,8 @@ abstract class BaseTraitTest extends TestCase public $logoutRedirect = '/login?fromlogout=1'; + public $loginAction = '/login-page'; + /** * SetUp and create Trait * @@ -129,7 +131,7 @@ protected function _mockRequestGet($withSession = false) $methods = ['is', 'referer', 'getData']; if ($withSession) { - $methods[] = 'session'; + $methods[] = 'getSession'; } $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') @@ -177,51 +179,13 @@ protected function _mockRequestPost($with = 'post') * @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 Auth and retur user id 1 - * - * @return void - */ - protected function _setAuthenticationIdentity($user = []) { $user += [ 'id' => '00000000-0000-0000-0000-000000000001', 'password' => '12345', ]; - $identity = new Identity(new User($user)); - $this->Trait->request = $this->Trait->request->withAttribute('identity', $identity); - } - - /** - * 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(); + $this->_mockAuthentication($user); } /** @@ -264,7 +228,8 @@ protected function _mockAuthentication($user = null) $registry = new ComponentRegistry($controller); $this->Trait->Authentication = new AuthenticationComponent($registry, [ 'loginRedirect' => $this->successLoginRedirect, - 'logoutRedirect' => $this->logoutRedirect + 'logoutRedirect' => $this->logoutRedirect, + 'loginAction' => $this->loginAction ]);; } diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index b78d49310..d812b7ce2 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -131,7 +131,7 @@ public function testLinkSocialHappy() 'provider' => 'facebook' ]); - $this->_setAuthenticationIdentity(); + $this->_mockAuthLoggedIn(); $this->_mockDispatchEvent(new Event('event')); $this->_mockFlash(); @@ -254,7 +254,7 @@ public function testCallbackLinkSocialHappy() ->method('getUsersTable') ->will($this->returnValue($Table)); - $this->_setAuthenticationIdentity(); + $this->_mockAuthLoggedIn(); $this->_mockDispatchEvent(new Event('event')); $this->_mockFlash(); $this->Trait->Flash->expects($this->never()) @@ -400,7 +400,7 @@ public function testCallbackLinkSocialWithValidationErrors() 'provider' => 'facebook' ]); - $this->_setAuthenticationIdentity(); + $this->_mockAuthLoggedIn(); $this->_mockDispatchEvent(new Event('event')); $this->_mockFlash(); $this->Trait->Flash->expects($this->once()) @@ -464,7 +464,7 @@ public function testCallbackLinkSocialQueryHasErrors() 'action' => 'profile' ])) ->will($this->returnValue(new Response())); - $this->_setAuthenticationIdentity(); + $this->_mockAuthLoggedIn(); $this->_mockDispatchEvent(new Event('event')); $this->_mockFlash(); $this->Trait->Flash->expects($this->never()) @@ -527,7 +527,7 @@ public function testCallbackLinkSocialUnknownProvider() 'action' => 'profile' ])) ->will($this->returnValue(new Response())); - $this->_setAuthenticationIdentity(); + $this->_mockAuthLoggedIn(); $this->_mockDispatchEvent(new Event('event')); $this->_mockFlash(); $this->Trait->Flash->expects($this->never()) diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index f4d292765..55e6d94a8 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -254,7 +254,7 @@ public function testChangePasswordGetLoggedIn() public function testChangePasswordGetNotLoggedInInsideResetPasswordFlow() { $this->_mockRequestGet(true); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->_mockSession([ Configure::read('Users.Key.Session.resetPasswordUserId') => '00000000-0000-0000-0000-000000000001' @@ -277,7 +277,7 @@ public function testChangePasswordGetNotLoggedInInsideResetPasswordFlow() public function testChangePasswordGetNotLoggedInOutsideResetPasswordFlow() { $this->_mockRequestGet(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->Trait->Flash->expects($this->once()) ->method('error') diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php index f0ab42c68..243e77fce 100644 --- a/tests/TestCase/Controller/Traits/ProfileTraitTest.php +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -48,7 +48,7 @@ public function testProfileGetNotLoggedInUserNotFound() { $userId = '00000000-0000-0000-0000-000000000000'; //not found $this->_mockRequestGet(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->Trait->Flash->expects($this->once()) ->method('error') @@ -81,7 +81,7 @@ public function testProfileGetLoggedInUserNotFound() public function testProfileGetNotLoggedInEmptyId() { $this->_mockRequestGet(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->Trait->Flash->expects($this->once()) ->method('error') diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index ec2a005d9..7dbcc7a73 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -68,7 +68,7 @@ public function testRegister() { $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) @@ -101,7 +101,7 @@ public function testRegisterWithEventFalseResult() { $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->_mockDispatchEvent(new Event('Users.Component.UsersAuth.beforeRegister'), ['username' => 'hello']); $this->Trait->Flash->expects($this->once()) @@ -133,7 +133,7 @@ public function testRegisterWithEventSuccessResult() $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->_mockDispatchEvent(new Event('Users.Component.UsersAuth.beforeRegister'), $data); $this->Trait->request->expects($this->once()) @@ -162,7 +162,7 @@ public function testRegisterReCaptcha() Configure::write('Users.reCaptcha.registration', true); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) @@ -200,7 +200,7 @@ public function testRegisterValidationErrors() Configure::write('Users.reCaptcha.registration', true); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) @@ -237,7 +237,7 @@ public function testRegisterRecaptchaNotValid() Configure::write('Users.reCaptcha.registration', true); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) @@ -271,7 +271,7 @@ public function testRegisterGet() { $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestGet(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->never()) @@ -295,7 +295,7 @@ public function testRegisterRecaptchaDisabled() Configure::write('Users.Registration.reCaptcha', false); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->Flash->expects($this->once()) @@ -332,7 +332,7 @@ public function testRegisterNotEnabled() { Configure::write('Users.Registration.active', false); $this->_mockRequestPost(); - $this->_mockAuth(); + $this->_mockAuthentication(); $this->_mockFlash(); $this->_mockDispatchEvent(); $this->Trait->register(); From 39b2cb0554816e47791483eafadfd8ed19311fdd Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Jun 2018 13:54:57 -0300 Subject: [PATCH 037/685] fixed import --- src/Controller/Traits/ProfileTrait.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index d6b72be24..15a01a0c2 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -15,6 +15,7 @@ use Cake\Core\Configure; use Cake\Datasource\Exception\InvalidPrimaryKeyException; use Cake\Datasource\Exception\RecordNotFoundException; +use Cake\Utility\Hash; /** * Covers the profile action From 5089fca862c6b6260643d463ab9f91120ef3af64 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Jun 2018 14:22:29 -0300 Subject: [PATCH 038/685] social trait should test based on middleware --- .../Controller/Traits/SocialTraitTest.php | 203 +++++++----------- 1 file changed, 81 insertions(+), 122 deletions(-) diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index 054bc7cb1..76b33eb64 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -12,169 +12,128 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use Cake\Core\Configure; +use Cake\Http\Response; +use Cake\Http\ServerRequest; use Cake\TestSuite\TestCase; +use CakeDC\Users\Middleware\SocialAuthMiddleware; -class SocialTraitTest extends TestCase +class SocialTraitTest extends BaseTraitTest { + /** + * setup + * + * @return void + */ public function setUp() { + $this->traitClassName = 'CakeDC\Users\Controller\Traits\SocialTrait'; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set', '_afterIdentifyUser']; + parent::setUp(); - $this->controller = $this->getMockBuilder('Cake\Controller\Controller') - ->setMethods(['header', 'redirect', 'render', '_stop']) - ->getMock(); + $request = new ServerRequest(); + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\SocialTrait') + ->setMethods(['dispatchEvent', 'redirect', 'set', '_afterIdentifyUser']) + ->getMockForTrait(); - $this->controller->Trait = $this->getMockForTrait( - 'CakeDC\Users\Controller\Traits\SocialTrait', - [], - '', - true, - true, - true, - ['_getOpauthInstance', 'redirect', '_generateOpauthCompleteUrl', '_afterIdentifyUser', '_validateRegisterPost'] - ); + $this->Trait->request = $request; } + /** + * tearDown + * + * @return void + */ public function tearDown() { parent::tearDown(); } /** - * Test socialEmail + * Test socialEmail get * */ - public function testSocialEmail() + public function testSocialEmailHappyGet() { - $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->Trait->request = $this->getMockBuilder('Cake\Network\Request') + ->setMethods(['is']) + ->getMock(); + $this->Trait->request->expects($this->any()) + ->method('is') + ->with('post') + ->will($this->returnValue(false)); + $this->_mockAuthentication(); + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['error']) + ->disableOriginalConstructor() + ->getMock(); + $this->Trait->Flash->expects($this->never()) + ->method('error'); + $this->Trait->expects($this->never()) + ->method('_afterIdentifyUser'); + $this->Trait->expects($this->never()) + ->method('redirect'); - $this->controller->Trait->socialEmail(); + $this->Trait->socialEmail(); } - /** * Test socialEmail * - * @expectedException \Cake\Http\Exception\NotFoundException */ - public function testSocialEmailInvalid() + public function testSocialEmailHappy() { - $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()) + $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->controller->Trait->expects($this->once()) - ->method('_validateRegisterPost') - ->will($this->returnValue(false)); - - $this->controller->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + $this->_mockAuthentication([ + 'id' => 1 + ]); + $this->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(); + $this->Trait->Flash->expects($this->never()) + ->method('error'); + $user = $this->Trait->request->getAttribute('identity')->getOriginalData(); + $response = new Response(); + $response->withStringBody("testSocialEmailHappy"); + $this->Trait->expects($this->once()) + ->method('_afterIdentifyUser') + ->with($user) + ->will($this->returnValue($response)); + + $this->assertSame($response, $this->Trait->socialEmail()); } - public function testSocialEmailPostValidateTrue() + /** + * Test socialEmail + * + */ + public function testSocialEmailInvalidRecaptcha() { - $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()) + $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->controller->Trait->expects($this->once()) - ->method('_validateRegisterPost') - ->will($this->returnValue(true)); - - $this->controller->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') - ->setMethods(['identify']) + $this->_mockAuthentication(); + $this->Trait->request = $this->Trait->request->withAttribute('socialAuthStatus', SocialAuthMiddleware::AUTH_ERROR_INVALID_RECAPTCHA); + $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') + ->setMethods(['error']) ->disableOriginalConstructor() ->getMock(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The reCaptcha could not be validated'); - $this->controller->Trait->Auth->expects($this->once()) - ->method('identify'); - - $this->controller->Trait->expects($this->once()) + $this->Trait->expects($this->never()) ->method('_afterIdentifyUser'); - $this->controller->Trait->socialEmail(); + $this->Trait->socialEmail(); } } From 7d4c3324530f3f7054a122ac3cc4d5fcd7617a1f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Jun 2018 14:45:55 -0300 Subject: [PATCH 039/685] fixing is IsAuthorizedTrait::checkRbacPermissions to use correct user data --- src/Traits/IsAuthorizedTrait.php | 3 +- .../View/Helper/AuthLinkHelperTest.php | 132 +++++++++++------- 2 files changed, 85 insertions(+), 50 deletions(-) diff --git a/src/Traits/IsAuthorizedTrait.php b/src/Traits/IsAuthorizedTrait.php index aac096cc3..adf311ac6 100644 --- a/src/Traits/IsAuthorizedTrait.php +++ b/src/Traits/IsAuthorizedTrait.php @@ -66,8 +66,7 @@ protected function checkRbacPermissions($url) $user = $this->request->getAttribute('identity'); $userData = []; if ($user) { - $userData = Hash::get($user, 'User', []); - $userData = is_object($userData) ? $userData->toArray() : $userData; + $userData = $user->getOriginalData()->toArray(); } return $Rbac->checkPermissions($userData, $targetRequest); diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php index 3817c10ef..03558651e 100644 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -11,6 +11,9 @@ namespace CakeDC\Users\Test\TestCase\View\Helper; +use Authentication\Identity; +use CakeDC\Auth\Rbac\Rbac; +use CakeDC\Users\Model\Entity\User; use CakeDC\Users\View\Helper\AuthLinkHelper; use CakeDC\Users\View\Helper\UserHelper; use Cake\Event\Event; @@ -62,7 +65,7 @@ public function tearDown() */ public function testLinkFalse() { - $link = $this->AuthLink->link('title', ['controller' => 'noaccess']); + $link = $this->AuthLink->link('title', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); $this->assertSame(false, $link); } @@ -71,22 +74,53 @@ public function testLinkFalse() * * @return void */ - public function testLinkAuthorized() + public function testLinkFalseWithMock() { - $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)); + $user = new User([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'password' => '12345' + ]); + $identity = new Identity($user); + $this->AuthLink->request = $this->AuthLink->request->withAttribute('identity', $identity); + $rbac = $this->getMockBuilder(Rbac::class)->setMethods(['checkPermissions'])->getMock(); + $rbac->expects($this->once()) + ->method('checkPermissions') + ->with($identity->getOriginalData()->toArray()) + ->will($this->returnValue(false)); + $this->AuthLink->request = $this->AuthLink->request->withAttribute('rbac', $rbac); + $result = $this->AuthLink->link( + 'title', + ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], + ['before' => 'before_', 'after' => '_after', 'class' => 'link-class'] + ); + $this->assertFalse($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 testLinkAuthorizedHappy() + { + $user = new User([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'password' => '12345' + ]); + $identity = new Identity($user); + $this->AuthLink->request = $this->AuthLink->request->withAttribute('identity', $identity); + $rbac = $this->getMockBuilder(Rbac::class)->setMethods(['checkPermissions'])->getMock(); + $rbac->expects($this->once()) + ->method('checkPermissions') + ->with($identity->getOriginalData()->toArray()) + ->will($this->returnValue(true)); + $this->AuthLink->request = $this->AuthLink->request->withAttribute('rbac', $rbac); + $link = $this->AuthLink->link( + 'title', + ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], + ['before' => 'before_', 'after' => '_after', 'class' => 'link-class'] + ); + $this->assertSame('before_title_after', $link); } /** @@ -96,17 +130,6 @@ public function testLinkAuthorized() */ 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); } @@ -118,15 +141,6 @@ public function testLinkAuthorizedAllowedTrue() */ 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); } @@ -138,19 +152,41 @@ public function testLinkAuthorizedAllowedFalse() */ 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']); + $user = new User([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'password' => '12345' + ]); + $identity = new Identity($user); + $this->AuthLink->request = $this->AuthLink->request->withAttribute('identity', $identity); + $rbac = $this->getMockBuilder(Rbac::class)->setMethods(['checkPermissions'])->getMock(); + $rbac->expects($this->once()) + ->method('checkPermissions') + ->with($identity->getOriginalData()->toArray()) + ->will($this->returnValue(true)); + $this->AuthLink->request = $this->AuthLink->request->withAttribute('rbac', $rbac); + $result = $this->AuthLink->isAuthorized(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); $this->assertTrue($result); } + /** + * Test isAuthorized + * + * @return void + */ + public function testIsAuthorizedFalse() + { + $user = new User([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'password' => '12345' + ]); + $identity = new Identity($user); + $this->AuthLink->request = $this->AuthLink->request->withAttribute('identity', $identity); + $rbac = $this->getMockBuilder(Rbac::class)->setMethods(['checkPermissions'])->getMock(); + $rbac->expects($this->once()) + ->method('checkPermissions') + ->with($identity->getOriginalData()->toArray()) + ->will($this->returnValue(false)); + $this->AuthLink->request = $this->AuthLink->request->withAttribute('rbac', $rbac); + $result = $this->AuthLink->isAuthorized(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); + $this->assertFalse($result); + } } From 6735d9ebeac1041087c6f859ac3f9441d7643bb7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Jun 2018 14:55:29 -0300 Subject: [PATCH 040/685] Using cake test case as base class --- tests/TestCase/Social/Service/ServiceFactoryTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/TestCase/Social/Service/ServiceFactoryTest.php b/tests/TestCase/Social/Service/ServiceFactoryTest.php index 940d3397f..51e17a88e 100644 --- a/tests/TestCase/Social/Service/ServiceFactoryTest.php +++ b/tests/TestCase/Social/Service/ServiceFactoryTest.php @@ -5,11 +5,12 @@ use Cake\Core\Configure; use Cake\Http\ServerRequestFactory; use Cake\Network\Exception\NotFoundException; +use Cake\TestSuite\TestCase; use CakeDC\Users\Social\Service\OAuth1Service; use CakeDC\Users\Social\Service\OAuth2Service; use CakeDC\Users\Social\Service\ServiceFactory; -class ServiceFactoryTest extends \PHPUnit_Framework_TestCase +class ServiceFactoryTest extends TestCase { /** From 87ac944b0cf96064d8fcbd379c4eb240a7cac1a5 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 29 Jun 2018 19:40:51 -0300 Subject: [PATCH 041/685] Plugin object compatible with new version of cakephp/authentication --- src/Authenticator/FormAuthenticator.php | 12 ++ src/Plugin.php | 23 +- tests/TestCase/PluginTest.php | 276 ++++++++++++++++++++++++ 3 files changed, 308 insertions(+), 3 deletions(-) create mode 100644 tests/TestCase/PluginTest.php diff --git a/src/Authenticator/FormAuthenticator.php b/src/Authenticator/FormAuthenticator.php index bf02b0308..0acaed8f2 100644 --- a/src/Authenticator/FormAuthenticator.php +++ b/src/Authenticator/FormAuthenticator.php @@ -122,4 +122,16 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface return $this->lastResult = new Result(null, self::FAILURE_INVALID_RECAPTCHA); } + + /** + * Call base authenticator methods + * + * @param string $name + * @param array $arguments + * @return mixed + */ + public function __call($name, $arguments) + { + return $this->getBaseAuthenticator()->$name(...$arguments); + } } \ No newline at end of file diff --git a/src/Plugin.php b/src/Plugin.php index eb36a2922..2a65511cf 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -1,25 +1,42 @@ authentication(); + } + /** * load authenticators and identifiers * - * @param AuthenticationServiceInterface $service Base authentication service * @return AuthenticationServiceInterface */ - public function authentication(AuthenticationServiceInterface $service) + public function authentication() { + $service = new AuthenticationService(); $authenticators = Configure::read('Auth.Authenticators'); $identifiers = Configure::read('Auth.Identifiers'); diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php new file mode 100644 index 000000000..e40e411d0 --- /dev/null +++ b/tests/TestCase/PluginTest.php @@ -0,0 +1,276 @@ +middleware($middleware); + $this->assertInstanceOf(SocialAuthMiddleware::class, $middleware->get(0)); + $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); + $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); + $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(3)); + $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(4)); + } + + /** + * testMiddleware + * + * @return void + */ + public function testMiddlewareNotSocial() + { + Configure::write('Users.Social.login', false); + Configure::write('Users.GoogleAuthenticator.login', true); + $plugin = new Plugin(); + + $middleware = new MiddlewareQueue(); + + $middleware = $plugin->middleware($middleware); + $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(0)); + $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(1)); + $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(2)); + } + + /** + * testMiddleware + * + * @return void + */ + public function testMiddlewareNotGoogleAuthenticator() + { + Configure::write('Users.Social.login', true); + Configure::write('Users.GoogleAuthenticator.login', false); + $plugin = new Plugin(); + + $middleware = new MiddlewareQueue(); + + $middleware = $plugin->middleware($middleware); + $this->assertInstanceOf(SocialAuthMiddleware::class, $middleware->get(0)); + $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); + $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); + $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(3)); + } + + /** + * testMiddleware + * + * @return void + */ + public function testMiddlewareNotGoogleAuthenticationAndNotSocial() + { + Configure::write('Users.Social.login', false); + Configure::write('Users.GoogleAuthenticator.login', false); + $plugin = new Plugin(); + + $middleware = new MiddlewareQueue(); + + $middleware = $plugin->middleware($middleware); + $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(0)); + $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(1)); + } + + /** + * testGetAuthenticationService + * + * @return void + */ + public function testGetAuthenticationService() + { + Configure::write('Auth.Authenticators', [ + 'Authentication.Session' => [ + 'skipGoogleVerify' => true, + 'sessionKey' => 'CustomAuth', + 'fields' => ['username' => 'email'], + 'identify' => true, + ], + 'CakeDC/Users.Form' => [ + 'loginUrl' => '/login', + 'fields' => ['username' => 'email', 'password' => 'alt_password'], + ], + 'Authentication.Token' => [ + 'skipGoogleVerify' => true, + 'header' => null, + 'queryParam' => 'api_key', + 'tokenPrefix' => null, + ], + ]); + Configure::write('Auth.Identifiers', [ + 'Authentication.Password' => [ + 'fields' => [ + 'username' => 'email_2', + 'password' => 'password_2' + ], + ], + 'Authentication.Token' => [ + 'tokenField' => 'api_token' + ], + 'Authentication.JwtSubject' + ]); + Configure::write('Users.GoogleAuthenticator.login', true); + + $plugin = new Plugin(); + $service = $plugin->getAuthenticationService(new ServerRequest(), new Response()); + $this->assertInstanceOf(AuthenticationService::class, $service); + + /** + * @var \Authentication\Authenticator\AuthenticatorCollection $authenticators + */ + $authenticators = $service->authenticators(); + $expected = [ + SessionAuthenticator::class => [ + 'fields' => ['username' => 'email'], + 'sessionKey' => 'CustomAuth', + 'identify' => true, + 'identityAttribute' => 'identity', + 'skipGoogleVerify' => true + ], + FormAuthenticator::class => [ + 'loginUrl' => '/login', + 'urlChecker' => 'Authentication.Default', + 'fields' => ['username' => 'email', 'password' => 'alt_password'] + ], + TokenAuthenticator::class => [ + 'header' => null, + 'queryParam' => 'api_key', + 'tokenPrefix' => null, + 'skipGoogleVerify' => true + ], + GoogleTwoFactorAuthenticator::class => [ + 'loginUrl' => null, + 'urlChecker' => 'Authentication.Default', + 'skipGoogleVerify' => true + ] + ]; + + /** + * @var \Authentication\Authenticator\AuthenticatorCollection $authenticators + */ + $identifiers = $service->identifiers(); + $expected = [ + PasswordIdentifier::class => [ + 'fields' => [ + 'username' => 'email_2', + 'password' => 'password_2' + ], + 'resolver' => 'Authentication.Orm', + 'passwordHasher' => null + ], + TokenIdentifier::class => [ + 'tokenField' => 'api_token', + 'dataField' => 'token', + 'resolver' => 'Authentication.Orm' + ], + JwtSubjectIdentifier::class => [ + 'tokenField' => 'id', + 'dataField' => 'sub', + 'resolver' => 'Authentication.Orm' + ] + ]; + $actual = []; + foreach ($identifiers as $key => $value) { + $actual[get_class($value)] = $value->getConfig(); + } + $this->assertEquals($expected, $actual); + } + + /** + * testGetAuthenticationService + * + * @return void + */ + public function testGetAuthenticationServiceWithouGoogleAuthenticator() + { + Configure::write('Auth.Authenticators', [ + 'Authentication.Session' => [ + 'skipGoogleVerify' => true, + 'sessionKey' => 'CustomAuth', + 'fields' => ['username' => 'email'], + 'identify' => true, + ], + 'CakeDC/Users.Form' => [ + 'loginUrl' => '/login', + 'fields' => ['username' => 'email', 'password' => 'alt_password'], + ], + 'Authentication.Token' => [ + 'skipGoogleVerify' => true, + 'header' => null, + 'queryParam' => 'api_key', + 'tokenPrefix' => null, + ], + ]); + Configure::write('Auth.Identifiers', [ + 'Authentication.Password', + 'Authentication.Token' => [ + 'tokenField' => 'api_token' + ], + 'Authentication.JwtSubject' + ]); + Configure::write('Users.GoogleAuthenticator.login', false); + + $plugin = new Plugin(); + $service = $plugin->getAuthenticationService(new ServerRequest(), new Response()); + $this->assertInstanceOf(AuthenticationService::class, $service); + + /** + * @var \Authentication\Authenticator\AuthenticatorCollection $authenticators + */ + $authenticators = $service->authenticators(); + $expected = [ + SessionAuthenticator::class => [ + 'fields' => ['username' => 'email'], + 'sessionKey' => 'CustomAuth', + 'identify' => true, + 'identityAttribute' => 'identity', + 'skipGoogleVerify' => true + ], + FormAuthenticator::class => [ + 'loginUrl' => '/login', + 'urlChecker' => 'Authentication.Default', + 'fields' => ['username' => 'email', 'password' => 'alt_password'] + ], + TokenAuthenticator::class => [ + 'header' => null, + 'queryParam' => 'api_key', + 'tokenPrefix' => null, + 'skipGoogleVerify' => true + ] + ]; + } +} From 303169033dd607c628c339ae521f9135ded3b3d0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 2 Jul 2018 17:21:24 -0300 Subject: [PATCH 042/685] created custom authentication service to work with 2Factor Authentication without saving data at Auth at the first step --- src/Authentication/AuthenticationService.php | 93 ++++++++++ src/Controller/Traits/LoginTrait.php | 1 + .../GoogleAuthenticatorMiddleware.php | 28 +-- src/Plugin.php | 6 +- .../AuthenticationServiceTest.php | 168 ++++++++++++++++++ tests/TestCase/PluginTest.php | 7 +- 6 files changed, 277 insertions(+), 26 deletions(-) create mode 100644 src/Authentication/AuthenticationService.php create mode 100644 tests/TestCase/Authentication/AuthenticationServiceTest.php diff --git a/src/Authentication/AuthenticationService.php b/src/Authentication/AuthenticationService.php new file mode 100644 index 000000000..09a71bc32 --- /dev/null +++ b/src/Authentication/AuthenticationService.php @@ -0,0 +1,93 @@ +getSession()->write('temporarySession', $result->getData()); + + $result = new Result(null, self::NEED_GOOGLE_VERIFY); + + $this->_successfulAuthenticator = null; + $this->_result = $result; + + return compact('result', 'request', 'response'); + } + + /** + * {@inheritDoc} + * + * @throws \RuntimeException Throws a runtime exception when no authenticators are loaded. + */ + public function authenticate(ServerRequestInterface $request, ResponseInterface $response) + { + if ($this->authenticators()->isEmpty()) { + throw new RuntimeException( + 'No authenticators loaded. You need to load at least one authenticator.' + ); + } + + $googleVerify = Configure::read('Users.GoogleAuthenticator.login'); + + $result = null; + foreach ($this->authenticators() as $authenticator) { + $result = $authenticator->authenticate($request, $response); + + if ($result->isValid()) { + if ($googleVerify !== false && $authenticator->getConfig('skipGoogleVerify') !== true) { + return $this->proceedToGoogleVerify($request, $response, $result); + } + + if (!($authenticator instanceof StatelessInterface)) { + $requestResponse = $this->persistIdentity($request, $response, $result->getData()); + $request = $requestResponse['request']; + $response = $requestResponse['response']; + } + + $this->_successfulAuthenticator = $authenticator; + $this->_result = $result; + + return [ + 'result' => $result, + 'request' => $request, + 'response' => $response + ]; + } + + if (!$result->isValid() && $authenticator instanceof StatelessInterface) { + $authenticator->unauthorizedChallenge($request); + } + } + + $this->_successfulAuthenticator = null; + $this->_result = $result; + + return [ + 'result' => $result, + 'request' => $request, + 'response' => $response + ]; + } + +} \ No newline at end of file diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index c3f2f55ba..394a4ad76 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -115,6 +115,7 @@ public function socialLogin() */ public function login() { + $this->request->getSession()->delete('temporarySession'); $result = $this->request->getAttribute('authentication')->getResult(); if ($result->isValid()) { diff --git a/src/Middleware/GoogleAuthenticatorMiddleware.php b/src/Middleware/GoogleAuthenticatorMiddleware.php index 8e58cb76e..04aabb402 100644 --- a/src/Middleware/GoogleAuthenticatorMiddleware.php +++ b/src/Middleware/GoogleAuthenticatorMiddleware.php @@ -2,18 +2,13 @@ namespace CakeDC\Users\Middleware; -use Authentication\Authenticator\FormAuthenticator; -use Cake\Core\InstanceConfigTrait; use Cake\Http\ServerRequest; -use Cake\Log\LogTrait; use Cake\Routing\Router; +use CakeDC\Users\Authentication\AuthenticationService; use Psr\Http\Message\ResponseInterface; class GoogleAuthenticatorMiddleware { - use InstanceConfigTrait; - use LogTrait; - /** * Proceed to second step of two factor authentication. See CakeDC\Users\Controller\Traits\verify * @@ -24,34 +19,25 @@ class GoogleAuthenticatorMiddleware */ public function __invoke(ServerRequest $request, ResponseInterface $response, $next) { - $identity = $request->getAttribute('identity'); - if (!$identity) { - return $next($request, $response); - } - $service = $request->getAttribute('authentication'); - if ($service->getAuthenticationProvider()->getConfig('skipGoogleVerify') === true) { + if (!$service->getResult() || $service->getResult()->getStatus() !== AuthenticationService::NEED_GOOGLE_VERIFY) { return $next($request, $response); } - $result = $service->clearIdentity($request, $response); - $request = $result['request']; - $response = $result['response']; - $request = $request->withoutAttribute('identity'); - $request = $request->withoutAttribute('authentication'); - $request = $request->withoutAttribute('authenticationResult'); - $request->getSession()->write('temporarySession', $identity->getOriginalData()); $request->getSession()->write('CookieAuth', [ 'remember_me' => $request->getData('remember_me') ]); - $url = Router::url(['action' => 'verify']); + $url = Router::url([ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'verify' + ]); return $response ->withHeader('Location', $url) ->withStatus(302); - } } \ No newline at end of file diff --git a/src/Plugin.php b/src/Plugin.php index 2a65511cf..9d4f660e8 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -1,13 +1,14 @@ add($authentication); + if (Configure::read('Users.GoogleAuthenticator.login')) { - $middlewareQueue->add('CakeDC\Users\Middleware\GoogleAuthenticatorMiddleware'); + $middlewareQueue->add(GoogleAuthenticatorMiddleware::class); } $middlewareQueue->add(new RbacMiddleware(null, [ diff --git a/tests/TestCase/Authentication/AuthenticationServiceTest.php b/tests/TestCase/Authentication/AuthenticationServiceTest.php new file mode 100644 index 000000000..f511367fb --- /dev/null +++ b/tests/TestCase/Authentication/AuthenticationServiceTest.php @@ -0,0 +1,168 @@ +get('CakeDC/Users.Users'); + $entity = $Table->get('00000000-0000-0000-0000-000000000001'); + $entity->password = 'password'; + $this->assertTrue((bool)$Table->save($entity)); + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/testpath'], + [], + ['username' => 'user-1', 'password' => 'password'] + ); + $response = new Response(); + + $service = new AuthenticationService([ + 'identifiers' => [ + 'Authentication.Password' + ], + 'authenticators' => [ + 'Authentication.Session', + 'CakeDC/Users.Form' + ] + ]); + + $result = $service->authenticate($request, $response); + $this->assertInstanceOf(Result::class, $result['result']); + $this->assertInstanceOf(ServerRequestInterface::class, $result['request']); + $this->assertInstanceOf(ResponseInterface::class, $result['response']); + + $this->assertTrue($result['result']->isValid()); + + $result = $service->getAuthenticationProvider(); + $this->assertInstanceOf(FormAuthenticator::class, $result); + + $this->assertEquals( + 'user-1', + $request->getAttribute('session')->read('Auth.username') + ); + $this->assertEmpty($response->getHeaderLine('Location')); + $this->assertNull($response->getStatusCode()); + } + + /** + * testAuthenticate + * + * @return void + */ + public function testAuthenticateShouldDoGoogleVerifyEnabled() + { + Configure::write('Users.GoogleAuthenticator.login', true); + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $entity = $Table->get('00000000-0000-0000-0000-000000000001'); + $entity->password = 'password'; + $this->assertTrue((bool)$Table->save($entity)); + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/testpath'], + [], + ['username' => 'user-1', 'password' => 'password'] + ); + $response = new Response(); + + $service = new AuthenticationService([ + 'identifiers' => [ + 'Authentication.Password' => [] + ], + 'authenticators' => [ + 'Authentication.Session' => [ + 'skipGoogleVerify' => true, + ], + 'CakeDC/Users.Form' => [ + 'skipGoogleVerify' => false, + ] + ] + ]); + + $result = $service->authenticate($request, $response); + $this->assertInstanceOf(Result::class, $result['result']); + $this->assertInstanceOf(ServerRequestInterface::class, $result['request']); + $this->assertInstanceOf(ResponseInterface::class, $result['response']); + $this->assertFalse($result['result']->isValid()); + $this->assertEquals(AuthenticationService::NEED_GOOGLE_VERIFY, $result['result']->getStatus()); + $this->assertEquals('/users/users/verify', $result['response']->getHeaderLine('Location')); + $this->assertEquals(302, $result['response']->getStatusCode()); + $this->assertNull($request->getAttribute('session')->read('Auth.username')); + + } + + /** + * testAuthenticate + * + * @return void + */ + public function testAuthenticateShouldDoGoogleVerifyDisabled() + { + Configure::write('Users.GoogleAuthenticator.login', false); + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $entity = $Table->get('00000000-0000-0000-0000-000000000001'); + $entity->password = 'password'; + $this->assertTrue((bool)$Table->save($entity)); + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/testpath'], + [], + ['username' => 'user-1', 'password' => 'password'] + ); + $response = new Response(); + + $service = new AuthenticationService([ + 'identifiers' => [ + 'Authentication.Password' => [] + ], + 'authenticators' => [ + 'Authentication.Session' => [ + 'skipGoogleVerify' => true, + ], + 'CakeDC/Users.Form' => [ + 'skipGoogleVerify' => false, + ] + ] + ]); + + $result = $service->authenticate($request, $response); + $this->assertInstanceOf(Result::class, $result['result']); + $this->assertInstanceOf(ServerRequestInterface::class, $result['request']); + $this->assertInstanceOf(ResponseInterface::class, $result['response']); + + $this->assertTrue($result['result']->isValid()); + + $result = $service->getAuthenticationProvider(); + $this->assertInstanceOf(FormAuthenticator::class, $result); + + $this->assertEquals( + 'user-1', + $request->getAttribute('session')->read('Auth.username') + ); + $this->assertEmpty($response->getHeaderLine('Location')); + $this->assertNull($response->getStatusCode()); + + } +} diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index e40e411d0..bb90be7cd 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -2,7 +2,6 @@ namespace CakeDC\Users\Test\TestCase; -use Authentication\AuthenticationService; use Authentication\Authenticator\SessionAuthenticator; use Authentication\Authenticator\TokenAuthenticator; use Authentication\Identifier\JwtSubjectIdentifier; @@ -14,6 +13,7 @@ use Cake\Http\Response; use Cake\Http\ServerRequest; use CakeDC\Auth\Middleware\RbacMiddleware; +use CakeDC\Users\Authentication\AuthenticationService as CakeDCAuthenticationService; use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\GoogleTwoFactorAuthenticator; use CakeDC\Users\Middleware\GoogleAuthenticatorMiddleware; @@ -106,6 +106,7 @@ public function testMiddlewareNotGoogleAuthenticationAndNotSocial() $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(1)); } + /** * testGetAuthenticationService * @@ -147,7 +148,7 @@ public function testGetAuthenticationService() $plugin = new Plugin(); $service = $plugin->getAuthenticationService(new ServerRequest(), new Response()); - $this->assertInstanceOf(AuthenticationService::class, $service); + $this->assertInstanceOf(CakeDCAuthenticationService::class, $service); /** * @var \Authentication\Authenticator\AuthenticatorCollection $authenticators @@ -246,7 +247,7 @@ public function testGetAuthenticationServiceWithouGoogleAuthenticator() $plugin = new Plugin(); $service = $plugin->getAuthenticationService(new ServerRequest(), new Response()); - $this->assertInstanceOf(AuthenticationService::class, $service); + $this->assertInstanceOf(CakeDCAuthenticationService::class, $service); /** * @var \Authentication\Authenticator\AuthenticatorCollection $authenticators From 9295564748d214942c6cd0fed7fa451f9e25de85 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 15:20:38 -0300 Subject: [PATCH 043/685] removed unused code after merge --- .../Controller/Traits/LoginTraitTest.php | 315 +----------------- 1 file changed, 4 insertions(+), 311 deletions(-) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 917dcdec8..edac1e471 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -70,7 +70,7 @@ public function tearDown() public function testLoginHappy() { $this->_mockDispatchEvent(new Event('event')); - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is']) ->getMock(); $this->Trait->request->expects($this->any()) @@ -100,9 +100,9 @@ public function testLoginHappy() */ public function testLoginGet() { - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is']) - ->disableOriginalConstructor() ->getMock(); $this->Trait->request->expects($this->once()) ->method('is') @@ -112,6 +112,7 @@ public function testLoginGet() ->setMethods(['error']) ->disableOriginalConstructor() ->getMock(); + $this->Trait->Flash->expects($this->never()) ->method('error'); @@ -247,312 +248,4 @@ public function testFailedSocialUserAccount() $this->Trait->failedSocialLogin(null, $data, true); } - - /** - * 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->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; - } } From 629508f722be133d9cf1fc67ede6441c0c085f9b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 15:21:15 -0300 Subject: [PATCH 044/685] fixing deprecated method --- .../Component/GoogleAuthenticatorComponentTest.php | 2 +- tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php | 2 +- tests/TestCase/Controller/Traits/SocialTraitTest.php | 6 +++--- tests/TestCase/View/Helper/UserHelperTest.php | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index c1e665b55..e10545f8d 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -59,7 +59,7 @@ public function setUp() Configure::write('App.namespace', 'Users'); Configure::write('Users.GoogleAuthenticator.login', true); - $this->request = $this->getMockBuilder('Cake\Network\Request') + $this->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is', 'method']) ->getMock(); $this->request->expects($this->any())->method('is')->will($this->returnValue(true)); diff --git a/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php b/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php index 845501bd2..437e181d9 100644 --- a/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php +++ b/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php @@ -67,7 +67,7 @@ public function tearDown() public function testVerifyHappy() { Configure::write('Users.GoogleAuthenticator.login', true); - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is', 'getData', 'allow', 'getSession']) ->getMock(); $this->Trait->request->expects($this->once()) diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index 76b33eb64..f73dbaee1 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -54,7 +54,7 @@ public function tearDown() */ public function testSocialEmailHappyGet() { - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is']) ->getMock(); $this->Trait->request->expects($this->any()) @@ -81,7 +81,7 @@ public function testSocialEmailHappyGet() */ public function testSocialEmailHappy() { - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is']) ->getMock(); $this->Trait->request->expects($this->any()) @@ -114,7 +114,7 @@ public function testSocialEmailHappy() */ public function testSocialEmailInvalidRecaptcha() { - $this->Trait->request = $this->getMockBuilder('Cake\Network\Request') + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is']) ->getMock(); $this->Trait->request->expects($this->any()) diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index f0bf717f0..481087adb 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -143,7 +143,7 @@ public function testWelcome() ->with('Auth.User.first_name') ->will($this->returnValue('david')); - $this->User->request = $this->getMockBuilder('Cake\Network\Request') + $this->User->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['getSession']) ->getMock(); $this->User->request->expects($this->any()) @@ -170,7 +170,7 @@ public function testWelcomeNotLoggedInUser() ->with('Auth.User.id') ->will($this->returnValue(null)); - $this->User->request = $this->getMockBuilder('Cake\Network\Request') + $this->User->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['getSession']) ->getMock(); $this->User->request->expects($this->any()) From 225ff900d0d51910882b50b2b5b84a3530940373 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 15:24:04 -0300 Subject: [PATCH 045/685] Remember me component was replaced by cookie authenticator --- .../Component/RememberMeComponent.php | 159 ------------------ 1 file changed, 159 deletions(-) delete mode 100644 src/Controller/Component/RememberMeComponent.php 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); - } -} From 71e97ac86bedc59ad2acf354ae29528e9f08ec6f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 15:35:21 -0300 Subject: [PATCH 046/685] move event constants to plugin object and removed users auth component --- .../Component/UsersAuthComponent.php | 49 ------------------- src/Controller/Traits/LoginTrait.php | 7 +-- src/Controller/Traits/RegisterTrait.php | 5 +- src/Model/Behavior/SocialBehavior.php | 3 +- src/Plugin.php | 7 +++ 5 files changed, 16 insertions(+), 55 deletions(-) delete mode 100644 src/Controller/Component/UsersAuthComponent.php diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php deleted file mode 100644 index 7efaf43e0..000000000 --- a/src/Controller/Component/UsersAuthComponent.php +++ /dev/null @@ -1,49 +0,0 @@ -dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGIN, ['user' => $user]); + $event = $this->dispatchEvent(Plugin::EVENT_AFTER_LOGIN, ['user' => $user]); if (is_array($event->result)) { return $this->redirect($event->result); } @@ -201,7 +202,7 @@ public function logout() { $user = $this->request->getAttribute('identity') ?? []; - $eventBefore = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_LOGOUT, ['user' => $user]); + $eventBefore = $this->dispatchEvent(Plugin::EVENT_BEFORE_LOGOUT, ['user' => $user]); if (is_array($eventBefore->result)) { return $this->redirect($eventBefore->result); } @@ -209,7 +210,7 @@ public function logout() $this->request->getSession()->destroy(); $this->Flash->success(__d('CakeDC/Users', 'You\'ve successfully logged out')); - $eventAfter = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGOUT, ['user' => $user]); + $eventAfter = $this->dispatchEvent(Plugin::EVENT_AFTER_LOGOUT, ['user' => $user]); if (is_array($eventAfter->result)) { return $this->redirect($eventAfter->result); } diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index e482ddfb1..b065e52b0 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -17,6 +17,7 @@ use Cake\Datasource\EntityInterface; use Cake\Http\Exception\NotFoundException; use Cake\Http\Response; +use CakeDC\Users\Plugin; /** * Covers registration features and email token validation @@ -57,7 +58,7 @@ public function register() 'use_tos' => $useTos ]; $requestData = $this->request->getData(); - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_REGISTER, [ + $event = $this->dispatchEvent(Plugin::EVENT_BEFORE_REGISTER, [ 'usersTable' => $usersTable, 'options' => $options, 'userEntity' => $user, @@ -132,7 +133,7 @@ protected function _afterRegister(EntityInterface $userSaved) if ($validateEmail) { $message = __d('CakeDC/Users', 'Please validate your account before log in'); } - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_REGISTER, [ + $event = $this->dispatchEvent(Plugin::EVENT_AFTER_REGISTER, [ 'user' => $userSaved ]); if ($event->result instanceof Response) { diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 7fdd2c0f0..411a2a8fe 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -15,6 +15,7 @@ use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; +use CakeDC\Users\Plugin; use CakeDC\Users\Traits\RandomStringTrait; use Cake\Datasource\EntityInterface; use Cake\Event\EventDispatcherTrait; @@ -127,7 +128,7 @@ protected function _createSocialUser($data, $options = []) $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_BEFORE_SOCIAL_LOGIN_USER_CREATE, [ + $event = $this->dispatchEvent(Plugin::EVENT_BEFORE_SOCIAL_LOGIN_USER_CREATE, [ 'userEntity' => $user, ]); if ($event->result instanceof EntityInterface) { diff --git a/src/Plugin.php b/src/Plugin.php index 9d4f660e8..77fb4eae9 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -16,7 +16,14 @@ class Plugin extends BasePlugin implements AuthenticationServiceProviderInterface { + const EVENT_AFTER_LOGIN = 'Users.Authentication.afterLogin'; + const EVENT_BEFORE_LOGOUT = 'Users.Authentication.beforeLogout'; + const EVENT_AFTER_LOGOUT = 'Users.Authentication.afterLogout'; + + const EVENT_BEFORE_REGISTER = 'Users.Managment.beforeRegister'; + const EVENT_AFTER_REGISTER = 'Users.Managment.afterRegister'; const EVENT_AFTER_CHANGE_PASSWORD = 'Users.Managment.afterResetPassword'; + const EVENT_BEFORE_SOCIAL_LOGIN_USER_CREATE = 'Users.Managment.beforeSocialLoginUserCreate'; /** * Returns an authentication service instance. From 59b2b4e3414feecfb5f5be0d97a17d86be300030 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 15:39:49 -0300 Subject: [PATCH 047/685] removed unused imports --- src/Authentication/AuthenticationService.php | 1 - src/Authenticator/GoogleTwoFactorAuthenticator.php | 1 - src/Controller/Component/GoogleAuthenticatorComponent.php | 3 --- src/Controller/SocialAccountsController.php | 1 - src/Controller/Traits/LinkSocialTrait.php | 4 ---- src/Controller/Traits/LoginTrait.php | 8 -------- src/Controller/Traits/PasswordManagementTrait.php | 2 -- src/Controller/Traits/SocialTrait.php | 1 - src/Controller/UsersController.php | 3 --- src/Http/BaseApplication.php | 1 - src/Listener/AuthListener.php | 1 - src/Model/Table/SocialAccountsTable.php | 1 - src/Model/Table/UsersTable.php | 2 -- src/Social/Locator/DatabaseLocator.php | 4 ---- src/Social/ProviderConfig.php | 1 - src/Traits/IsAuthorizedTrait.php | 1 - src/View/Helper/UserHelper.php | 1 - 17 files changed, 36 deletions(-) diff --git a/src/Authentication/AuthenticationService.php b/src/Authentication/AuthenticationService.php index 09a71bc32..eb8fc291d 100644 --- a/src/Authentication/AuthenticationService.php +++ b/src/Authentication/AuthenticationService.php @@ -7,7 +7,6 @@ use Authentication\Authenticator\ResultInterface; use Authentication\Authenticator\StatelessInterface; use Cake\Core\Configure; -use Cake\Routing\Router; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use RuntimeException; diff --git a/src/Authenticator/GoogleTwoFactorAuthenticator.php b/src/Authenticator/GoogleTwoFactorAuthenticator.php index 72ca6aa05..1b9240743 100644 --- a/src/Authenticator/GoogleTwoFactorAuthenticator.php +++ b/src/Authenticator/GoogleTwoFactorAuthenticator.php @@ -4,7 +4,6 @@ use Authentication\Authenticator\AbstractAuthenticator; use Authentication\Authenticator\Result; -use Authentication\Identifier\IdentifierInterface; use Authentication\UrlChecker\UrlCheckerTrait; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; diff --git a/src/Controller/Component/GoogleAuthenticatorComponent.php b/src/Controller/Component/GoogleAuthenticatorComponent.php index 71fab3cb6..8b590e477 100644 --- a/src/Controller/Component/GoogleAuthenticatorComponent.php +++ b/src/Controller/Component/GoogleAuthenticatorComponent.php @@ -13,9 +13,6 @@ use Cake\Controller\Component; use Cake\Core\Configure; -use Cake\Event\Event; -use Cake\Utility\Security; -use InvalidArgumentException; use RobThree\Auth\TwoFactorAuth; /** diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index acaa87d03..96eabccab 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Controller; -use CakeDC\Users\Controller\AppController; use CakeDC\Users\Exception\AccountAlreadyActiveException; use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Datasource\Exception\RecordNotFoundException; diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 33c6d522d..6e0adb8ec 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -12,11 +12,7 @@ namespace CakeDC\Users\Controller\Traits; use Cake\Utility\Hash; -use CakeDC\Users\Model\Table\SocialAccountsTable; -use Cake\Core\Configure; -use Cake\Http\Exception\NotFoundException; use CakeDC\Users\Social\Service\ServiceFactory; -use League\OAuth1\Client\Server\Twitter; /** * Ações para "linkar" contas sociais diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index be3e640a1..4c5ebe87d 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -16,18 +16,10 @@ use CakeDC\Users\Authenticator\AuthenticatorFeedbackInterface; use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Controller\Component\UsersAuthComponent; -use CakeDC\Users\Exception\AccountNotActiveException; -use CakeDC\Users\Exception\MissingEmailException; -use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Middleware\SocialAuthMiddleware; -use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Core\Configure; -use Cake\Core\Exception\Exception; -use Cake\Event\Event; use Cake\Http\Exception\NotFoundException; -use Cake\Utility\Hash; use CakeDC\Users\Plugin; -use League\OAuth1\Client\Server\Twitter; /** * Covers the login, logout and social login diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index b093b0663..6c4ad4f16 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -16,9 +16,7 @@ use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; use Cake\Core\Configure; -use Cake\Log\Log; use Cake\Validation\Validator; -use CakeDC\Users\Listener\AuthListener; use CakeDC\Users\Plugin; use Exception; diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 5d4937a10..44feca3b6 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; use CakeDC\Users\Middleware\SocialAuthMiddleware; diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 967c7e8a3..a1279fbc3 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Controller; -use CakeDC\Users\Controller\AppController; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Controller\Traits\GoogleVerifyTrait; use CakeDC\Users\Controller\Traits\LinkSocialTrait; @@ -22,8 +21,6 @@ use CakeDC\Users\Controller\Traits\SimpleCrudTrait; use CakeDC\Users\Controller\Traits\SocialTrait; use CakeDC\Users\Model\Table\UsersTable; -use Cake\Core\Configure; -use Cake\ORM\Table; /** * Users Controller diff --git a/src/Http/BaseApplication.php b/src/Http/BaseApplication.php index 8c3cb141c..dc9076e79 100644 --- a/src/Http/BaseApplication.php +++ b/src/Http/BaseApplication.php @@ -6,7 +6,6 @@ use Cake\Core\Configure; use Cake\Error\Middleware\ErrorHandlerMiddleware; use Cake\Http\BaseApplication as CakeBaseApplication; -use Cake\Log\Log; use Cake\Routing\Middleware\AssetMiddleware; use Cake\Routing\Middleware\RoutingMiddleware; use CakeDC\Auth\Middleware\RbacMiddleware; diff --git a/src/Listener/AuthListener.php b/src/Listener/AuthListener.php index e25c13674..d9eb1c567 100644 --- a/src/Listener/AuthListener.php +++ b/src/Listener/AuthListener.php @@ -1,7 +1,6 @@ Date: Tue, 3 Jul 2018 15:44:12 -0300 Subject: [PATCH 048/685] Remember me component was replaced by cookie authenticator --- .../Component/RememberMeComponentTest.php | 194 ------------------ 1 file changed, 194 deletions(-) delete mode 100644 tests/TestCase/Controller/Component/RememberMeComponentTest.php 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)); - } -} From 1344c648e760801642cbab2997115917bbbc8fee Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 15:48:10 -0300 Subject: [PATCH 049/685] move event constants to plugin object and removed users auth component --- src/Listener/AuthListener.php | 23 ----------------------- src/Middleware/SocialAuthMiddleware.php | 4 ++-- src/Plugin.php | 2 ++ src/Social/Locator/DatabaseLocator.php | 4 ++-- 4 files changed, 6 insertions(+), 27 deletions(-) delete mode 100644 src/Listener/AuthListener.php diff --git a/src/Listener/AuthListener.php b/src/Listener/AuthListener.php deleted file mode 100644 index d9eb1c567..000000000 --- a/src/Listener/AuthListener.php +++ /dev/null @@ -1,23 +0,0 @@ - $exception, 'rawData' => $data]; - $this->dispatchEvent( AuthListener::EVENT_FAILED_SOCIAL_LOGIN, $args); + $this->dispatchEvent(Plugin::EVENT_FAILED_SOCIAL_LOGIN, $args); return false; } diff --git a/src/Plugin.php b/src/Plugin.php index 77fb4eae9..5d5a263f3 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -19,6 +19,8 @@ class Plugin extends BasePlugin implements AuthenticationServiceProviderInterfac const EVENT_AFTER_LOGIN = 'Users.Authentication.afterLogin'; const EVENT_BEFORE_LOGOUT = 'Users.Authentication.beforeLogout'; const EVENT_AFTER_LOGOUT = 'Users.Authentication.afterLogout'; + const EVENT_FAILED_SOCIAL_LOGIN = 'Users.Authentication.failedSocialLogin'; + const EVENT_AFTER_SOCIAL_REGISTER = 'Users.Authentication.afterSocialRegister'; const EVENT_BEFORE_REGISTER = 'Users.Managment.beforeRegister'; const EVENT_AFTER_REGISTER = 'Users.Managment.afterRegister'; diff --git a/src/Social/Locator/DatabaseLocator.php b/src/Social/Locator/DatabaseLocator.php index 59a520df0..783ffaad7 100644 --- a/src/Social/Locator/DatabaseLocator.php +++ b/src/Social/Locator/DatabaseLocator.php @@ -7,8 +7,8 @@ use Cake\Event\EventDispatcherTrait; use Cake\ORM\TableRegistry; use CakeDC\Users\Auth\Exception\InvalidSettingsException; -use CakeDC\Users\Listener\AuthListener; use CakeDC\Users\Model\Entity\User; +use CakeDC\Users\Plugin; class DatabaseLocator implements LocatorInterface { @@ -54,7 +54,7 @@ public function getOrCreate(array $rawData): User } // If new SocialAccount was created $user is returned containing it if ($user->get('social_accounts')) { - $this->dispatchEvent(AuthListener::EVENT_AFTER_SOCIAL_REGISTER, compact('user')); + $this->dispatchEvent(Plugin::EVENT_AFTER_SOCIAL_REGISTER, compact('user')); } $user = $this->findUser($user)->firstOrFail(); From 39379eb7b037100726e4b0eb148927fb514d002b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 15:48:43 -0300 Subject: [PATCH 050/685] authentication service does set redirect for response --- .../TestCase/Authentication/AuthenticationServiceTest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/TestCase/Authentication/AuthenticationServiceTest.php b/tests/TestCase/Authentication/AuthenticationServiceTest.php index f511367fb..dd4d134ce 100644 --- a/tests/TestCase/Authentication/AuthenticationServiceTest.php +++ b/tests/TestCase/Authentication/AuthenticationServiceTest.php @@ -108,10 +108,11 @@ public function testAuthenticateShouldDoGoogleVerifyEnabled() $this->assertInstanceOf(ResponseInterface::class, $result['response']); $this->assertFalse($result['result']->isValid()); $this->assertEquals(AuthenticationService::NEED_GOOGLE_VERIFY, $result['result']->getStatus()); - $this->assertEquals('/users/users/verify', $result['response']->getHeaderLine('Location')); - $this->assertEquals(302, $result['response']->getStatusCode()); $this->assertNull($request->getAttribute('session')->read('Auth.username')); - + $this->assertEquals( + 'user-1', + $request->getAttribute('session')->read('temporarySession.username') + ); } /** From 8d75e461d8a395f6b1bf587ddb3f0625d86d16da Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 15:49:54 -0300 Subject: [PATCH 051/685] fixed deprecated methods --- src/Social/Locator/DatabaseLocator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Social/Locator/DatabaseLocator.php b/src/Social/Locator/DatabaseLocator.php index 783ffaad7..35ee6f3f4 100644 --- a/src/Social/Locator/DatabaseLocator.php +++ b/src/Social/Locator/DatabaseLocator.php @@ -72,7 +72,7 @@ public function getOrCreate(array $rawData): User protected function findUser($user) { $userModel = $this->getConfig('userModel'); - $table = TableRegistry::get($userModel); + $table = TableRegistry::getTableLocator()->get($userModel); $finder = $this->getConfig('finder'); $primaryKey = (array)$table->getPrimaryKey(); @@ -98,7 +98,7 @@ protected function _socialLogin($data) ]; $userModel = Configure::read('Users.table'); - $User = TableRegistry::get($userModel); + $User = TableRegistry::getTableLocator()->get($userModel); $user = $User->socialLogin($data, $options); return $user; From 36eadb977e53ca205853e2b4775fa3ddd03691e8 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 15:55:39 -0300 Subject: [PATCH 052/685] fixing error 'undefined class' --- src/Authenticator/FormAuthenticator.php | 4 +++- src/Controller/Traits/GoogleVerifyTrait.php | 4 ++-- src/Controller/Traits/LinkSocialTrait.php | 1 - src/Controller/Traits/LoginTrait.php | 1 - src/Controller/Traits/RegisterTrait.php | 1 - src/Controller/UsersController.php | 1 - src/Middleware/SocialAuthMiddleware.php | 1 + src/Model/Behavior/SocialBehavior.php | 1 - src/View/Helper/UserHelper.php | 1 - 9 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Authenticator/FormAuthenticator.php b/src/Authenticator/FormAuthenticator.php index 0acaed8f2..56a759840 100644 --- a/src/Authenticator/FormAuthenticator.php +++ b/src/Authenticator/FormAuthenticator.php @@ -33,7 +33,9 @@ class FormAuthenticator implements AuthenticatorInterface, AuthenticatorFeedback protected $identifier; /** - * @var settings for base authenticator + * Settings for base authenticator + * + * @var array */ protected $config; diff --git a/src/Controller/Traits/GoogleVerifyTrait.php b/src/Controller/Traits/GoogleVerifyTrait.php index 503a8efd6..2e3e79b0e 100644 --- a/src/Controller/Traits/GoogleVerifyTrait.php +++ b/src/Controller/Traits/GoogleVerifyTrait.php @@ -73,7 +73,7 @@ protected function isVerifyAllowed() /** * Get the Google Authenticator secret of user, if not exists try to create one and save * - * @param User $user user data present on session + * @param \CakeDC\Users\Model\Entity\User $user user data present on session * * @return string if empty the creation has failed */ @@ -138,7 +138,7 @@ protected function onPostVerifyCode($loginAction) * Handle the part of action when user post the form with valid code * * @param array $loginAction url to login page used in redirect - * @param User $user user data present on session + * @param \CakeDC\Users\Model\Entity\User $user user data present on session * * @return \Cake\Http\Response */ diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 6e0adb8ec..68fce232c 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -91,7 +91,6 @@ public function callbackLinkSocial($alias = null) * @param string $alias of the provider. * @param array $data User data. * - * @throws MissingProviderException * @return array */ protected function _mapSocialUser($alias, $data) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 4c5ebe87d..8cd814d49 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -15,7 +15,6 @@ use Authentication\Authenticator\Result; use CakeDC\Users\Authenticator\AuthenticatorFeedbackInterface; use CakeDC\Users\Authenticator\FormAuthenticator; -use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Middleware\SocialAuthMiddleware; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index b065e52b0..83cdf5ca6 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -12,7 +12,6 @@ namespace CakeDC\Users\Controller\Traits; use Cake\Utility\Hash; -use CakeDC\Users\Controller\Component\UsersAuthComponent; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Http\Exception\NotFoundException; diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index a1279fbc3..f1ea5deb0 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Controller; -use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Controller\Traits\GoogleVerifyTrait; use CakeDC\Users\Controller\Traits\LinkSocialTrait; use CakeDC\Users\Controller\Traits\LoginTrait; diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 5f6a83b32..31ac6d3da 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -3,6 +3,7 @@ namespace CakeDC\Users\Middleware; use Cake\Core\InstanceConfigTrait; +use Cake\Datasource\Exception\RecordNotFoundException; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 411a2a8fe..539e1cb4f 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Model\Behavior; -use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 2bf5d06ce..ef50f9b29 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\View\Helper; -use CakeDC\Users\Controller\Component\UsersAuthComponent; use Cake\Core\Configure; use Cake\Utility\Hash; use Cake\Utility\Inflector; From 457489783e9b1a4e57ba28ff25171487a1e40eda Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 16:11:37 -0300 Subject: [PATCH 053/685] fixing deprecated method --- .../TestCase/Controller/Traits/LinkSocialTraitTest.php | 10 +++++----- tests/TestCase/Middleware/SocialAuthMiddlewareTest.php | 6 +++--- .../TestCase/Middleware/SocialEmailMiddlewareTest.php | 8 ++++---- tests/TestCase/Social/Service/ServiceFactoryTest.php | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index d812b7ce2..786905977 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -124,7 +124,7 @@ public function testLinkSocialHappy() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $this->Trait->request = $this->Trait->request->addParams([ + $this->Trait->request = $this->Trait->request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial', @@ -243,7 +243,7 @@ public function testCallbackLinkSocialHappy() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $this->Trait->request = $this->Trait->request->addParams([ + $this->Trait->request = $this->Trait->request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial', @@ -393,7 +393,7 @@ public function testCallbackLinkSocialWithValidationErrors() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $this->Trait->request = $this->Trait->request->addParams([ + $this->Trait->request = $this->Trait->request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial', @@ -448,7 +448,7 @@ public function testCallbackLinkSocialQueryHasErrors() $uri = new Uri('/callback-link-social/facebook'); $this->Trait->request = $this->Trait->request->withUri($uri); - $this->Trait->request = $this->Trait->request->addParams([ + $this->Trait->request = $this->Trait->request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial', @@ -511,7 +511,7 @@ public function testCallbackLinkSocialUnknownProvider() $uri = new Uri('/callback-link-social/facebook'); $this->Trait->request = $this->Trait->request->withUri($uri); - $this->Trait->request = $this->Trait->request->addParams([ + $this->Trait->request = $this->Trait->request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial', diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index fc2b0b41b..7aacb9185 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -114,7 +114,7 @@ public function testProceedStepOne() $uri = new Uri('/auth/facebook'); $this->Request = $this->Request->withUri($uri); - $this->Request = $this->Request->addParams([ + $this->Request = $this->Request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', @@ -164,7 +164,7 @@ public function testSuccessfullyAuthenticated() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $this->Request = $this->Request->addParams([ + $this->Request = $this->Request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', @@ -259,7 +259,7 @@ public function testErrorGetUser() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $this->Request = $this->Request->addParams([ + $this->Request = $this->Request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index 434c32095..5e0e0d0f0 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -132,7 +132,7 @@ public function testWithGetRquest() $uri = new Uri('/auth/facebook'); $this->Request = $this->Request->withUri($uri); - $this->Request = $this->Request->addParams([ + $this->Request = $this->Request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail', @@ -166,7 +166,7 @@ public function testWithoutUser() 'email' => 'example@example.com' ]); $this->Request = $this->Request->withMethod('POST'); - $this->Request = $this->Request->addParams([ + $this->Request = $this->Request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail', @@ -242,7 +242,7 @@ public function testSuccessfullyAuthenticated() 'email' => 'example@example.com' ]); $this->Request = $this->Request->withMethod('POST'); - $this->Request = $this->Request->addParams([ + $this->Request = $this->Request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail', @@ -322,7 +322,7 @@ public function testWithoutEmail() $uri = new Uri('/auth/facebook'); $this->Request = $this->Request->withUri($uri); $this->Request = $this->Request->withMethod('POST'); - $this->Request = $this->Request->addParams([ + $this->Request = $this->Request->withAttribute('params',[ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail', diff --git a/tests/TestCase/Social/Service/ServiceFactoryTest.php b/tests/TestCase/Social/Service/ServiceFactoryTest.php index 51e17a88e..d45e94c25 100644 --- a/tests/TestCase/Social/Service/ServiceFactoryTest.php +++ b/tests/TestCase/Social/Service/ServiceFactoryTest.php @@ -68,7 +68,7 @@ public function testCreateFromRequest() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $request = $request->addParams([ + $request = $request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', @@ -141,7 +141,7 @@ public function testCreateFromRequestCustomRedirectUriField() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $request = $request->addParams([ + $request = $request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', @@ -209,7 +209,7 @@ public function testCreateFromRequestOAuth1() Configure::write('OAuth.providers.twitter', $config); $request = ServerRequestFactory::fromGlobals(); - $request = $request->addParams([ + $request = $request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', @@ -233,7 +233,7 @@ public function testCreateFromRequestProviderNotEnabled() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $request = $request->addParams([ + $request = $request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', From 02889f0759f2db765982351f716bd58170bb3e54 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 16:13:08 -0300 Subject: [PATCH 054/685] fixing deprecated method --- tests/TestCase/Controller/Traits/LinkSocialTraitTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 786905977..7219d1dfe 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -167,7 +167,7 @@ public function testCallbackLinkSocialHappy() Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - $Table = TableRegistry::get('CakeDC/Users.Users'); + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $Token = new \League\OAuth2\Client\Token\AccessToken([ 'access_token' => 'test-token', @@ -298,7 +298,7 @@ public function testCallbackLinkSocialWithValidationErrors() { Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - $user = TableRegistry::get('akeDC/Users.Users')->get('00000000-0000-0000-0000-000000000001'); + $user = TableRegistry::getTableLocator()->get('akeDC/Users.Users')->get('00000000-0000-0000-0000-000000000001'); $user->setErrors([ 'social_accounts' => [ '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') @@ -425,7 +425,7 @@ public function testCallbackLinkSocialQueryHasErrors() Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - $Table = TableRegistry::get('CakeDC/Users.Users'); + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $this->Provider->expects($this->never()) ->method('getAuthorizationUrl'); @@ -488,7 +488,7 @@ public function testCallbackLinkSocialUnknownProvider() Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - $Table = TableRegistry::get('CakeDC/Users.Users'); + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $this->Provider->expects($this->never()) ->method('getAuthorizationUrl'); From 3c19820d7798c8eb46559dc86aa7779d7cff95cf Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 16:16:00 -0300 Subject: [PATCH 055/685] fixing deprecated method --- tests/bootstrap.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index e94978c62..cde392bea 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -98,9 +98,6 @@ 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 From ff1818f22aa340a960ae37488d95fc9807919833 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Jul 2018 16:21:19 -0300 Subject: [PATCH 056/685] remove base application since the logic was moved to plugin object --- src/Http/BaseApplication.php | 102 ----------------------------------- 1 file changed, 102 deletions(-) delete mode 100644 src/Http/BaseApplication.php diff --git a/src/Http/BaseApplication.php b/src/Http/BaseApplication.php deleted file mode 100644 index dc9076e79..000000000 --- a/src/Http/BaseApplication.php +++ /dev/null @@ -1,102 +0,0 @@ - $options) { - if (is_numeric($identifier)) { - $identifier = $options; - $options = []; - } - - $service->loadIdentifier($identifier, $options); - } - - foreach($authenticators as $authenticator => $options) { - if (is_numeric($authenticator)) { - $authenticator = $options; - $options = []; - } - - $service->loadAuthenticator($authenticator, $options); - } - - if (Configure::read('Users.GoogleAuthenticator.login')) { - $service->loadAuthenticator('CakeDC/Users.GoogleTwoFactor', [ - 'skipGoogleVerify' => true, - ]); - } - - return $service; - } - - /** - * Setup the middleware queue your application will use. - * - * @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to setup. - * @return \Cake\Http\MiddlewareQueue The updated middleware queue. - */ - public function middleware($middlewareQueue) - { - $middlewareQueue - // Catch any exceptions in the lower layers, - // and make an error page/response - ->add(ErrorHandlerMiddleware::class) - - // Handle plugin/theme assets like CakePHP normally does. - ->add(AssetMiddleware::class) - - // Add routing middleware. - ->add(new RoutingMiddleware($this)); - - if (Configure::read('Users.Social.login')) { - $middlewareQueue - ->add(SocialAuthMiddleware::class) - ->add(SocialEmailMiddleware::class); - } - - $authentication = new AuthenticationMiddleware($this); - $middlewareQueue->add($authentication); - if (Configure::read('Users.GoogleAuthenticator.login')) { - $middlewareQueue->add('CakeDC\Users\Middleware\GoogleAuthenticatorMiddleware'); - } - - $middlewareQueue->add(new RbacMiddleware(null, [ - 'unauthorizedRedirect' => [ - 'prefix' => false, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - ] - ])); - - return $middlewareQueue; - } -} \ No newline at end of file From e347871a092c8572e9fa01619a02cbb167bc1e27 Mon Sep 17 00:00:00 2001 From: Chokri K Date: Tue, 24 Jul 2018 15:59:35 +0100 Subject: [PATCH 057/685] adding data-theme, data-size and data-tabindex to addReCaptcha function --- src/View/Helper/UserHelper.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index c1f4cb7b7..90f2c8150 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -11,9 +11,7 @@ namespace CakeDC\Users\View\Helper; -use CakeDC\Users\Controller\Component\UsersAuthComponent; use Cake\Core\Configure; -use Cake\Event\Event; use Cake\Utility\Hash; use Cake\Utility\Inflector; use Cake\View\Helper; @@ -57,7 +55,7 @@ public function socialLogin($name, $options = []) $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 + 'escape' => false, 'class' => $providerClass, ]); } @@ -100,7 +98,7 @@ public function socialLoginList(array $providerOptions = []) public function logout($message = null, $options = []) { return $this->AuthLink->link(empty($message) ? __d('CakeDC/Users', 'Logout') : $message, [ - 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout' + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout', ], $options); } @@ -146,7 +144,10 @@ public function addReCaptcha() return $this->Html->tag('div', '', [ 'class' => 'g-recaptcha', - 'data-sitekey' => Configure::read('Users.reCaptcha.key') + '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', ]); } @@ -212,7 +213,7 @@ public function socialConnectLink($name, $provider, $isConnected = false) "/link-social/$name", [ 'escape' => false, - 'class' => $linkClass + 'class' => $linkClass, ] ); } @@ -232,7 +233,7 @@ public function socialConnectLinkList($socialAccounts = []) $html = ""; $connectedProviders = array_map(function ($item) { return strtolower($item->provider); - }, (array)$socialAccounts); + }, (array) $socialAccounts); $providers = Configure::read('OAuth.providers'); foreach ($providers as $name => $provider) { From 4c22787f75f8b1f3013b91f7c8f5c62cfbdd97d4 Mon Sep 17 00:00:00 2001 From: Chokri K Date: Thu, 26 Jul 2018 17:42:47 +0100 Subject: [PATCH 058/685] fix the testAddReCaptcha --- phpunit.xml | 36 +++++++++++++++++++ tests/TestCase/View/Helper/UserHelperTest.php | 5 ++- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 phpunit.xml diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 000000000..500c19975 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + ./tests/TestCase + + + + + ./src + + + + + + + + + + + + diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index e20b30e77..fd3f987e0 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -190,8 +190,11 @@ public function testWelcomeNotLoggedInUser() 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); + $this->assertEquals('
', $result); } /** From e203ce660872934cab9c370abc1c3ffb69031abd Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 28 Jul 2018 11:08:44 -0300 Subject: [PATCH 059/685] using cakephp/authorization plugin --- config/permissions.php | 3 - config/users.php | 9 ++- src/Controller/AppController.php | 29 +++++++- src/Plugin.php | 57 +++++++++++++--- tests/TestCase/PluginTest.php | 112 ++++++++++++++++++++++++++++++- 5 files changed, 193 insertions(+), 17 deletions(-) diff --git a/config/permissions.php b/config/permissions.php index 04a6bf41f..15ad90800 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -71,9 +71,6 @@ 'requestResetPassword', // UserValidationTrait used in PasswordManagementTrait 'resendTokenValidation', - // Social - 'endpoint', - 'authenticated', ], 'bypassAuth' => true, ], diff --git a/config/users.php b/config/users.php index 44b97f7db..bf7ffb77a 100644 --- a/config/users.php +++ b/config/users.php @@ -125,7 +125,6 @@ 'prefix' => false, ], ], - // default configuration used to auto-load the Auth Component, override to change the way Auth works 'Auth' => [ 'AuthenticationComponent' => [ 'loginAction' => '/login', @@ -163,6 +162,14 @@ 'tokenField' => 'api_token' ] ], + "Authorization" => [ + 'enable' => true, + 'loadAuthorizationMiddleware' => true, + 'loadRbacMiddleware' => false, + ], + 'AuthorizationComponent' => [ + 'enabled' => true, + ] ], 'SocialAuthMiddleware' => [ 'sessionAuthKey' => 'Auth', diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index 06307e8da..f72d6b530 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -20,6 +20,27 @@ */ class AppController extends BaseController { + protected $_defaultAuthorizationConfig = [ + 'skipAuthorization' => [ + 'validateAccount', + // LoginTrait + 'socialLogin', + 'login', + 'logout', + 'socialEmail', + 'verify', + // RegisterTrait + 'register', + 'validateEmail', + // PasswordManagementTrait used in RegisterTrait + 'changePassword', + 'resetPassword', + 'requestResetPassword', + // UserValidationTrait used in PasswordManagementTrait + 'resendTokenValidation', + ] + ]; + /** * Initialize * @@ -34,7 +55,13 @@ public function initialize() } $this->loadComponent('Authentication.Authentication', Configure::read('Auth.AuthenticationComponent')); - if (Configure::read('Users.GoogleAuthenticator.login')) { + if (Configure::read('Auth.AuthorizationComponent.enable') !== false) { + $config = (array)Configure::read('Auth.AuthorizationComponent') + $this->_defaultAuthorizationConfig; + + $this->loadComponent('Authorization.Authorization', $config); + } + + if (Configure::read('Users.GoogleAuthenticator.login') !== false) { $this->loadComponent('CakeDC/Users.GoogleAuthenticator'); } } diff --git a/src/Plugin.php b/src/Plugin.php index 5d5a263f3..ef6a9c0bb 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -4,8 +4,13 @@ use Authentication\AuthenticationServiceInterface; use Authentication\AuthenticationServiceProviderInterface; use Authentication\Middleware\AuthenticationMiddleware; +use Authorization\AuthorizationService; +use Authorization\AuthorizationServiceProviderInterface; +use Authorization\Middleware\AuthorizationMiddleware; +use Authorization\Policy\OrmResolver; use Cake\Core\BasePlugin; use Cake\Core\Configure; +use Cake\Http\MiddlewareQueue; use CakeDC\Auth\Middleware\RbacMiddleware; use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Middleware\GoogleAuthenticatorMiddleware; @@ -14,7 +19,7 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -class Plugin extends BasePlugin implements AuthenticationServiceProviderInterface +class Plugin extends BasePlugin implements AuthenticationServiceProviderInterface, AuthorizationServiceProviderInterface { const EVENT_AFTER_LOGIN = 'Users.Authentication.afterLogin'; const EVENT_BEFORE_LOGOUT = 'Users.Authentication.beforeLogout'; @@ -39,6 +44,17 @@ public function getAuthenticationService(ServerRequestInterface $request, Respon return $this->authentication(); } + /** + * {@inheritdoc} + */ + public function getAuthorizationService(ServerRequestInterface $request, ResponseInterface $response) + { + $resolver = new OrmResolver(); + + return new AuthorizationService($resolver); + } + + /** * load authenticators and identifiers * @@ -95,14 +111,37 @@ public function middleware($middlewareQueue) $middlewareQueue->add(GoogleAuthenticatorMiddleware::class); } - $middlewareQueue->add(new RbacMiddleware(null, [ - 'unauthorizedRedirect' => [ - 'prefix' => false, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - ] - ])); + $middlewareQueue = $this->addAuthorizationMiddleware($middlewareQueue); + + return $middlewareQueue; + } + + /** + * Add authorization middleware based on Auth.Authorization + * + * @param MiddlewareQueue $middlewareQueue + * @return MiddlewareQueue + */ + protected function addAuthorizationMiddleware(MiddlewareQueue $middlewareQueue) + { + if (Configure::read('Auth.Authorization.enable') === false) { + return $middlewareQueue; + } + + if (Configure::read('Auth.Authorization.loadAuthorizationMiddleware') !== false) { + $middlewareQueue->add(new AuthorizationMiddleware($this)); + } + + if (Configure::read('Auth.Authorization.loadRbacMiddleware') !== false) { + $middlewareQueue->add(new RbacMiddleware(null, [ + 'unauthorizedRedirect' => [ + 'prefix' => false, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + ] + ])); + } return $middlewareQueue; } diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index bb90be7cd..ad99f5a9c 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -8,6 +8,8 @@ use Authentication\Identifier\PasswordIdentifier; use Authentication\Identifier\TokenIdentifier; use Authentication\Middleware\AuthenticationMiddleware; +use Authorization\AuthorizationService; +use Authorization\Middleware\AuthorizationMiddleware; use Cake\Core\Configure; use Cake\Http\MiddlewareQueue; use Cake\Http\Response; @@ -37,6 +39,63 @@ public function testMiddleware() { Configure::write('Users.Social.login', true); Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Auth.Authorization.enable', true); + Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); + Configure::write('Auth.Authorization.loadRbacMiddleware', false); + + $plugin = new Plugin(); + + $middleware = new MiddlewareQueue(); + + $middleware = $plugin->middleware($middleware); + $this->assertInstanceOf(SocialAuthMiddleware::class, $middleware->get(0)); + $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); + $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); + $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(3)); + $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(4)); + $this->assertEquals(5, $middleware->count()); + } + + /** + * testMiddleware + * + * @return void + */ + public function testMiddlewareAuthorizationMiddlewareAndRbacMiddleware() + { + Configure::write('Users.Social.login', true); + Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Auth.Authorization.enable', true); + Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); + Configure::write('Auth.Authorization.loadRbacMiddleware', true); + + $plugin = new Plugin(); + + $middleware = new MiddlewareQueue(); + + $middleware = $plugin->middleware($middleware); + $this->assertInstanceOf(SocialAuthMiddleware::class, $middleware->get(0)); + $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); + $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); + $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(3)); + $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(4)); + $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(5)); + $this->assertEquals(6, $middleware->count()); + } + + /** + * testMiddleware + * + * @return void + */ + public function testMiddlewareAuthorizationOnlyRbacMiddleware() + { + Configure::write('Users.Social.login', true); + Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Auth.Authorization.enable', true); + Configure::write('Auth.Authorization.loadAuthorizationMiddleware', false); + Configure::write('Auth.Authorization.loadRbacMiddleware', true); + $plugin = new Plugin(); $middleware = new MiddlewareQueue(); @@ -47,6 +106,32 @@ public function testMiddleware() $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(3)); $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(4)); + $this->assertEquals(5, $middleware->count()); + } + + /** + * testMiddleware without authorization + * + * @return void + */ + public function testMiddlewareWithoutAuhorization() + { + Configure::write('Users.Social.login', true); + Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Auth.Authorization.enable', false); + Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true);//ignore + Configure::write('Auth.Authorization.loadRbacMiddleware', true);//ignore + + $plugin = new Plugin(); + + $middleware = new MiddlewareQueue(); + + $middleware = $plugin->middleware($middleware); + $this->assertInstanceOf(SocialAuthMiddleware::class, $middleware->get(0)); + $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); + $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); + $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(3)); + $this->assertEquals(4, $middleware->count()); } /** @@ -58,6 +143,9 @@ public function testMiddlewareNotSocial() { Configure::write('Users.Social.login', false); Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Auth.Authorization.enable', true); + Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); + Configure::write('Auth.Authorization.loadRbacMiddleware', false); $plugin = new Plugin(); $middleware = new MiddlewareQueue(); @@ -65,7 +153,7 @@ public function testMiddlewareNotSocial() $middleware = $plugin->middleware($middleware); $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(0)); $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(1)); - $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(2)); + $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(2)); } /** @@ -77,6 +165,9 @@ public function testMiddlewareNotGoogleAuthenticator() { Configure::write('Users.Social.login', true); Configure::write('Users.GoogleAuthenticator.login', false); + Configure::write('Auth.Authorization.enable', true); + Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); + Configure::write('Auth.Authorization.loadRbacMiddleware', false); $plugin = new Plugin(); $middleware = new MiddlewareQueue(); @@ -85,7 +176,7 @@ public function testMiddlewareNotGoogleAuthenticator() $this->assertInstanceOf(SocialAuthMiddleware::class, $middleware->get(0)); $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); - $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(3)); + $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(3)); } /** @@ -97,13 +188,16 @@ public function testMiddlewareNotGoogleAuthenticationAndNotSocial() { Configure::write('Users.Social.login', false); Configure::write('Users.GoogleAuthenticator.login', false); + Configure::write('Auth.Authorization.enable', true); + Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); + Configure::write('Auth.Authorization.loadRbacMiddleware', false); $plugin = new Plugin(); $middleware = new MiddlewareQueue(); $middleware = $plugin->middleware($middleware); $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(0)); - $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(1)); + $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(1)); } @@ -274,4 +368,16 @@ public function testGetAuthenticationServiceWithouGoogleAuthenticator() ] ]; } + + /** + * testGetAuthorizationService + * + * @return void + */ + public function testGetAuthorizationService() + { + $plugin = new Plugin(); + $service = $plugin->getAuthorizationService(new ServerRequest(), new Response()); + $this->assertInstanceOf(AuthorizationService::class, $service); + } } From 8e7b06d195b883545a2f4869c98a84427eda5d79 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 28 Jul 2018 14:10:05 -0300 Subject: [PATCH 060/685] authorization with RequestAuthorizationMiddleware. and Rbac policy --- config/permissions.php | 2 + src/Plugin.php | 18 ++++++- src/Policy/RbacPolicy.php | 24 +++++++++ tests/TestCase/PluginTest.php | 12 +++-- tests/TestCase/Policy/RbacPolicyTest.php | 65 ++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 src/Policy/RbacPolicy.php create mode 100644 tests/TestCase/Policy/RbacPolicyTest.php diff --git a/config/permissions.php b/config/permissions.php index 15ad90800..83ad91758 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -60,6 +60,7 @@ // LoginTrait 'socialLogin', 'login', + 'logout', 'socialEmail', 'verify', // RegisterTrait @@ -71,6 +72,7 @@ 'requestResetPassword', // UserValidationTrait used in PasswordManagementTrait 'resendTokenValidation', + 'linkSocial' ], 'bypassAuth' => true, ], diff --git a/src/Plugin.php b/src/Plugin.php index ef6a9c0bb..d5491dd03 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -7,15 +7,20 @@ use Authorization\AuthorizationService; use Authorization\AuthorizationServiceProviderInterface; use Authorization\Middleware\AuthorizationMiddleware; +use Authorization\Middleware\RequestAuthorizationMiddleware; +use Authorization\Policy\MapResolver; use Authorization\Policy\OrmResolver; +use Authorization\Policy\ResolverCollection; use Cake\Core\BasePlugin; use Cake\Core\Configure; use Cake\Http\MiddlewareQueue; +use Cake\Http\ServerRequest; use CakeDC\Auth\Middleware\RbacMiddleware; use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Middleware\GoogleAuthenticatorMiddleware; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; +use CakeDC\Users\Policy\RbacPolicy; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -49,8 +54,15 @@ public function getAuthenticationService(ServerRequestInterface $request, Respon */ public function getAuthorizationService(ServerRequestInterface $request, ResponseInterface $response) { - $resolver = new OrmResolver(); + $map = new MapResolver(); + $map->map(ServerRequest::class, RbacPolicy::class); + $orm = new OrmResolver(); + + $resolver = new ResolverCollection([ + $map, + $orm + ]); return new AuthorizationService($resolver); } @@ -129,7 +141,9 @@ protected function addAuthorizationMiddleware(MiddlewareQueue $middlewareQueue) } if (Configure::read('Auth.Authorization.loadAuthorizationMiddleware') !== false) { - $middlewareQueue->add(new AuthorizationMiddleware($this)); + $config = Configure::read('Auth.AuthorizationMiddleware'); + $middlewareQueue->add(new AuthorizationMiddleware($this, Configure::read('Auth.AuthorizationMiddleware'))); + $middlewareQueue->add(new RequestAuthorizationMiddleware()); } if (Configure::read('Auth.Authorization.loadRbacMiddleware') !== false) { diff --git a/src/Policy/RbacPolicy.php b/src/Policy/RbacPolicy.php new file mode 100644 index 000000000..6d53fa348 --- /dev/null +++ b/src/Policy/RbacPolicy.php @@ -0,0 +1,24 @@ +getAttribute('rbac') ?? new Rbac(); + + $user = $identity ? $identity->getOriginalData()->toArray() : []; + + return (bool)$rbac->checkPermissions($user, $resource); + } +} \ No newline at end of file diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index ad99f5a9c..2dced5856 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -10,6 +10,7 @@ use Authentication\Middleware\AuthenticationMiddleware; use Authorization\AuthorizationService; use Authorization\Middleware\AuthorizationMiddleware; +use Authorization\Middleware\RequestAuthorizationMiddleware; use Cake\Core\Configure; use Cake\Http\MiddlewareQueue; use Cake\Http\Response; @@ -53,7 +54,8 @@ public function testMiddleware() $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(3)); $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(4)); - $this->assertEquals(5, $middleware->count()); + $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->get(5)); + $this->assertEquals(6, $middleware->count()); } /** @@ -79,8 +81,9 @@ public function testMiddlewareAuthorizationMiddlewareAndRbacMiddleware() $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(3)); $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(4)); - $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(5)); - $this->assertEquals(6, $middleware->count()); + $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->get(5)); + $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(6)); + $this->assertEquals(7, $middleware->count()); } /** @@ -154,6 +157,7 @@ public function testMiddlewareNotSocial() $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(0)); $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(1)); $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(2)); + $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->get(3)); } /** @@ -177,6 +181,7 @@ public function testMiddlewareNotGoogleAuthenticator() $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(3)); + $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->get(4)); } /** @@ -198,6 +203,7 @@ public function testMiddlewareNotGoogleAuthenticationAndNotSocial() $middleware = $plugin->middleware($middleware); $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(0)); $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(1)); + $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->get(2)); } diff --git a/tests/TestCase/Policy/RbacPolicyTest.php b/tests/TestCase/Policy/RbacPolicyTest.php new file mode 100644 index 000000000..bd1ceb095 --- /dev/null +++ b/tests/TestCase/Policy/RbacPolicyTest.php @@ -0,0 +1,65 @@ + '00000000-0000-0000-0000-000000000001', + 'password' => '12345' + ]); + $identity = new Identity($user); + $request = ServerRequestFactory::fromGlobals(); + $request = $request->withAttribute('identity', $identity); + $rbac = $this->getMockBuilder(Rbac::class)->setMethods(['checkPermissions'])->getMock(); + $request = $request->withAttribute('rbac', $rbac); + $rbac->expects($this->once()) + ->method('checkPermissions') + ->with( + $this->equalTo($identity->getOriginalData()->toArray()), + $this->equalTo($request) + ) + ->will($this->returnValue(true)); + $policy = new RbacPolicy(); + $this->assertTrue($policy->canAccess($identity, $request)); + } + + /** + * Test before method, with rbac returning false + */ + public function testBeforeRbacReturnedFalse() + { + $user = new User([ + 'id' => '00000000-0000-0000-0000-000000000001', + 'password' => '12345' + ]); + $identity = new Identity($user); + $request = ServerRequestFactory::fromGlobals(); + $request = $request->withAttribute('identity', $identity); + $rbac = $this->getMockBuilder(Rbac::class)->setMethods(['checkPermissions'])->getMock(); + $request = $request->withAttribute('rbac', $rbac); + $rbac->expects($this->once()) + ->method('checkPermissions') + ->with( + $this->equalTo($identity->getOriginalData()->toArray()), + $this->equalTo($request) + ) + ->will($this->returnValue(false)); + $request = $request->withAttribute('rbac', $rbac); + $policy = new RbacPolicy(); + $this->assertFalse($policy->canAccess($identity, $request)); + } +} From febbdf370454a127035c99b457e7465890f51e8a Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 28 Jul 2018 14:10:55 -0300 Subject: [PATCH 061/685] config for authorization middleware --- config/users.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/config/users.php b/config/users.php index bf7ffb77a..8f89f8706 100644 --- a/config/users.php +++ b/config/users.php @@ -167,6 +167,19 @@ 'loadAuthorizationMiddleware' => true, 'loadRbacMiddleware' => false, ], + 'AuthorizationMiddleware' => [ + 'unauthorizedHandler' => [ + 'exceptions' => [ + 'MissingIdentityException' => 'Authorization\Exception\MissingIdentityException', + ], + 'className' => 'Authorization.CakeRedirect', + 'url' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + ] + ] + ], 'AuthorizationComponent' => [ 'enabled' => true, ] From a31d696f0b1640a500a5e1967e565293ed86bb5e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 28 Jul 2018 14:36:00 -0300 Subject: [PATCH 062/685] moved Auth/Social to Social namespace --- composer.json | 5 +++-- config/users.php | 12 ++++++------ src/Controller/Traits/LinkSocialTrait.php | 2 +- src/Middleware/SocialEmailMiddleware.php | 2 +- src/{Auth => }/Social/Mapper/AbstractMapper.php | 2 +- src/{Auth => }/Social/Mapper/Amazon.php | 2 +- src/{Auth => }/Social/Mapper/Facebook.php | 2 +- src/{Auth => }/Social/Mapper/Google.php | 2 +- src/{Auth => }/Social/Mapper/Instagram.php | 2 +- src/{Auth => }/Social/Mapper/LinkedIn.php | 2 +- src/{Auth => }/Social/Mapper/Twitter.php | 2 +- src/Social/Service/OAuth2Service.php | 2 +- src/Social/Service/ServiceFactory.php | 2 +- src/{Auth => }/Social/Util/SocialUtils.php | 2 +- .../Controller/Traits/LinkSocialTraitTest.php | 4 ++-- .../TestCase/Middleware/SocialAuthMiddlewareTest.php | 4 ++-- .../Middleware/SocialEmailMiddlewareTest.php | 4 ++-- .../TestCase/Social/Locator/DatabaseLocatorTest.php | 2 +- .../{Auth => }/Social/Mapper/FacebookTest.php | 4 ++-- .../TestCase/{Auth => }/Social/Mapper/GoogleTest.php | 4 ++-- .../{Auth => }/Social/Mapper/InstagramTest.php | 4 ++-- .../{Auth => }/Social/Mapper/LinkedInTest.php | 4 ++-- .../{Auth => }/Social/Mapper/TwitterTest.php | 4 ++-- tests/TestCase/Social/ProviderConfigTest.php | 12 ++++++------ tests/TestCase/Social/Service/OAuth1ServiceTest.php | 6 +++--- tests/TestCase/Social/Service/OAuth2ServiceTest.php | 4 ++-- tests/TestCase/Social/Service/ServiceFactoryTest.php | 10 +++++----- 27 files changed, 54 insertions(+), 53 deletions(-) rename src/{Auth => }/Social/Mapper/AbstractMapper.php (98%) rename src/{Auth => }/Social/Mapper/Amazon.php (95%) rename src/{Auth => }/Social/Mapper/Facebook.php (95%) rename src/{Auth => }/Social/Mapper/Google.php (95%) rename src/{Auth => }/Social/Mapper/Instagram.php (95%) rename src/{Auth => }/Social/Mapper/LinkedIn.php (94%) rename src/{Auth => }/Social/Mapper/Twitter.php (96%) rename src/{Auth => }/Social/Util/SocialUtils.php (95%) rename tests/TestCase/{Auth => }/Social/Mapper/FacebookTest.php (96%) rename tests/TestCase/{Auth => }/Social/Mapper/GoogleTest.php (95%) rename tests/TestCase/{Auth => }/Social/Mapper/InstagramTest.php (94%) rename tests/TestCase/{Auth => }/Social/Mapper/LinkedInTest.php (95%) rename tests/TestCase/{Auth => }/Social/Mapper/TwitterTest.php (94%) diff --git a/composer.json b/composer.json index bdef20dc6..ad2cca5c7 100644 --- a/composer.json +++ b/composer.json @@ -39,10 +39,11 @@ "league/oauth2-linkedin": "@stable", "luchianenco/oauth2-amazon": "^1.1", "google/recaptcha": "@stable", - "robthree/twofactorauth": "~1.6.0", + "robthree/twofactorauth": "^1.6", "satooshi/php-coveralls": "^2.0", + "league/oauth1-client": "^1.7", "cakephp/authentication": "^1.0@RC", - "league/oauth1-client": "^1.7" + "cakephp/authorization": "^1.0@beta" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", diff --git a/config/users.php b/config/users.php index 8f89f8706..ed62ccc6f 100644 --- a/config/users.php +++ b/config/users.php @@ -197,7 +197,7 @@ 'facebook' => [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'graphApiVersion' => 'v2.8', //bio field was deprecated on >= v2.8 'redirectUri' => Router::fullBaseUrl() . '/auth/facebook', @@ -208,7 +208,7 @@ 'twitter' => [ 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', 'className' => 'League\OAuth1\Client\Server\Twitter', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Twitter', + 'mapper' => 'CakeDC\Users\Social\Mapper\Twitter', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/twitter', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter', @@ -218,7 +218,7 @@ 'linkedIn' => [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\LinkedIn', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\LinkedIn', + 'mapper' => 'CakeDC\Users\Social\Mapper\LinkedIn', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/linkedIn', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/linkedIn', @@ -228,7 +228,7 @@ 'instagram' => [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Instagram', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Instagram', + 'mapper' => 'CakeDC\Users\Social\Mapper\Instagram', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/instagram', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/instagram', @@ -238,7 +238,7 @@ 'google' => [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Google', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Google', + 'mapper' => 'CakeDC\Users\Social\Mapper\Google', 'options' => [ 'userFields' => ['url', 'aboutMe'], 'redirectUri' => Router::fullBaseUrl() . '/auth/google', @@ -249,7 +249,7 @@ 'amazon' => [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'Luchianenco\OAuth2\Client\Provider\Amazon', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Amazon', + 'mapper' => 'CakeDC\Users\Social\Mapper\Amazon', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/amazon', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/amazon', diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 68fce232c..ba4d16fc4 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -96,7 +96,7 @@ public function callbackLinkSocial($alias = null) protected function _mapSocialUser($alias, $data) { $alias = ucfirst($alias); - $providerMapperClass = "\\CakeDC\\Users\\Auth\\Social\\Mapper\\$alias"; + $providerMapperClass = "\\CakeDC\\Users\\Social\\Mapper\\$alias"; $providerMapper = new $providerMapperClass($data); $user = $providerMapper(); $user['provider'] = $alias; diff --git a/src/Middleware/SocialEmailMiddleware.php b/src/Middleware/SocialEmailMiddleware.php index eed8845ad..44ea2360f 100644 --- a/src/Middleware/SocialEmailMiddleware.php +++ b/src/Middleware/SocialEmailMiddleware.php @@ -2,7 +2,7 @@ namespace CakeDC\Users\Middleware; -use Cake\Network\Exception\NotFoundException; +use Cake\Http\Exception\NotFoundException; use CakeDC\Users\Controller\Traits\ReCaptchaTrait; use Cake\Core\Configure; use Cake\Http\ServerRequest; diff --git a/src/Auth/Social/Mapper/AbstractMapper.php b/src/Social/Mapper/AbstractMapper.php similarity index 98% rename from src/Auth/Social/Mapper/AbstractMapper.php rename to src/Social/Mapper/AbstractMapper.php index e6e44d28f..a6aa3e791 100644 --- a/src/Auth/Social/Mapper/AbstractMapper.php +++ b/src/Social/Mapper/AbstractMapper.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Social\Mapper; +namespace CakeDC\Users\Social\Mapper; use Cake\Utility\Hash; diff --git a/src/Auth/Social/Mapper/Amazon.php b/src/Social/Mapper/Amazon.php similarity index 95% rename from src/Auth/Social/Mapper/Amazon.php rename to src/Social/Mapper/Amazon.php index 20c532052..1ca0709f0 100644 --- a/src/Auth/Social/Mapper/Amazon.php +++ b/src/Social/Mapper/Amazon.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Social\Mapper; +namespace CakeDC\Users\Social\Mapper; use Cake\Utility\Hash; diff --git a/src/Auth/Social/Mapper/Facebook.php b/src/Social/Mapper/Facebook.php similarity index 95% rename from src/Auth/Social/Mapper/Facebook.php rename to src/Social/Mapper/Facebook.php index b578fe82d..55951d666 100644 --- a/src/Auth/Social/Mapper/Facebook.php +++ b/src/Social/Mapper/Facebook.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Social\Mapper; +namespace CakeDC\Users\Social\Mapper; use Cake\Utility\Hash; diff --git a/src/Auth/Social/Mapper/Google.php b/src/Social/Mapper/Google.php similarity index 95% rename from src/Auth/Social/Mapper/Google.php rename to src/Social/Mapper/Google.php index b895d5361..c7bbfe551 100644 --- a/src/Auth/Social/Mapper/Google.php +++ b/src/Social/Mapper/Google.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Social\Mapper; +namespace CakeDC\Users\Social\Mapper; use Cake\Utility\Hash; diff --git a/src/Auth/Social/Mapper/Instagram.php b/src/Social/Mapper/Instagram.php similarity index 95% rename from src/Auth/Social/Mapper/Instagram.php rename to src/Social/Mapper/Instagram.php index b6adecf1d..44f8f9027 100644 --- a/src/Auth/Social/Mapper/Instagram.php +++ b/src/Social/Mapper/Instagram.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Social\Mapper; +namespace CakeDC\Users\Social\Mapper; use Cake\Utility\Hash; diff --git a/src/Auth/Social/Mapper/LinkedIn.php b/src/Social/Mapper/LinkedIn.php similarity index 94% rename from src/Auth/Social/Mapper/LinkedIn.php rename to src/Social/Mapper/LinkedIn.php index cadda4b3c..24c573b3e 100644 --- a/src/Auth/Social/Mapper/LinkedIn.php +++ b/src/Social/Mapper/LinkedIn.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Social\Mapper; +namespace CakeDC\Users\Social\Mapper; class LinkedIn extends AbstractMapper { diff --git a/src/Auth/Social/Mapper/Twitter.php b/src/Social/Mapper/Twitter.php similarity index 96% rename from src/Auth/Social/Mapper/Twitter.php rename to src/Social/Mapper/Twitter.php index 3dccfa45f..3ba6c5870 100644 --- a/src/Auth/Social/Mapper/Twitter.php +++ b/src/Social/Mapper/Twitter.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Social\Mapper; +namespace CakeDC\Users\Social\Mapper; use Cake\Utility\Hash; diff --git a/src/Social/Service/OAuth2Service.php b/src/Social/Service/OAuth2Service.php index 6678d9967..5e947d3bc 100644 --- a/src/Social/Service/OAuth2Service.php +++ b/src/Social/Service/OAuth2Service.php @@ -2,8 +2,8 @@ namespace CakeDC\Users\Social\Service; +use Cake\Http\Exception\BadRequestException; use Cake\Http\ServerRequest; -use Cake\Network\Exception\BadRequestException; use League\OAuth2\Client\Provider\AbstractProvider; class OAuth2Service extends OAuthServiceAbstract diff --git a/src/Social/Service/ServiceFactory.php b/src/Social/Service/ServiceFactory.php index 12f553100..6890b1a54 100644 --- a/src/Social/Service/ServiceFactory.php +++ b/src/Social/Service/ServiceFactory.php @@ -2,8 +2,8 @@ namespace CakeDC\Users\Social\Service; +use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequest; -use Cake\Network\Exception\NotFoundException; use CakeDC\Users\Social\ProviderConfig; class ServiceFactory diff --git a/src/Auth/Social/Util/SocialUtils.php b/src/Social/Util/SocialUtils.php similarity index 95% rename from src/Auth/Social/Util/SocialUtils.php rename to src/Social/Util/SocialUtils.php index 0ae12fbf1..5ae5dfb83 100644 --- a/src/Auth/Social/Util/SocialUtils.php +++ b/src/Social/Util/SocialUtils.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Social\Util; +namespace CakeDC\Users\Social\Util; use League\OAuth2\Client\Provider\AbstractProvider; use ReflectionClass; diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 7219d1dfe..2220849cc 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -78,7 +78,7 @@ public function setUp() $config = [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => $this->Provider, - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__', 'graphApiVersion' => 'v2.8', @@ -298,7 +298,7 @@ public function testCallbackLinkSocialWithValidationErrors() { Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - $user = TableRegistry::getTableLocator()->get('akeDC/Users.Users')->get('00000000-0000-0000-0000-000000000001'); + $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') diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index 7aacb9185..d40b6ac7c 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -13,7 +13,7 @@ use Cake\Http\ServerRequestFactory; use Cake\Routing\Router; use Cake\TestSuite\TestCase; -use CakeDC\Users\Auth\Social\Mapper\Facebook; +use CakeDC\Users\Social\Mapper\Facebook; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Model\Entity\User; use CakeDC\Users\Social\Service\OAuth2Service; @@ -67,7 +67,7 @@ public function setUp() $config = [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => $this->Provider, - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__', 'graphApiVersion' => 'v2.8', diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index 5e0e0d0f0..2556d5174 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -7,7 +7,7 @@ use Cake\Http\ServerRequestFactory; use Cake\Network\Exception\NotFoundException; use Cake\TestSuite\TestCase; -use CakeDC\Users\Auth\Social\Mapper\Facebook; +use CakeDC\Users\Social\Mapper\Facebook; use CakeDC\Users\Middleware\SocialEmailMiddleware; use CakeDC\Users\Model\Entity\User; use League\OAuth2\Client\Provider\FacebookUser; @@ -38,7 +38,7 @@ public function setUp() $config = [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__', 'graphApiVersion' => 'v2.8', diff --git a/tests/TestCase/Social/Locator/DatabaseLocatorTest.php b/tests/TestCase/Social/Locator/DatabaseLocatorTest.php index 5dc0ad845..0aa068480 100644 --- a/tests/TestCase/Social/Locator/DatabaseLocatorTest.php +++ b/tests/TestCase/Social/Locator/DatabaseLocatorTest.php @@ -5,7 +5,7 @@ use Cake\Datasource\Exception\RecordNotFoundException; use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Exception\InvalidSettingsException; -use CakeDC\Users\Auth\Social\Mapper\Facebook; +use CakeDC\Users\Social\Mapper\Facebook; use CakeDC\Users\Social\Locator\DatabaseLocator; class DatabaseLocatorTest extends TestCase diff --git a/tests/TestCase/Auth/Social/Mapper/FacebookTest.php b/tests/TestCase/Social/Mapper/FacebookTest.php similarity index 96% rename from tests/TestCase/Auth/Social/Mapper/FacebookTest.php rename to tests/TestCase/Social/Mapper/FacebookTest.php index 8c8ba9e85..353beef21 100644 --- a/tests/TestCase/Auth/Social/Mapper/FacebookTest.php +++ b/tests/TestCase/Social/Mapper/FacebookTest.php @@ -9,9 +9,9 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Test\TestCase\Auth\Social\Mapper; +namespace CakeDC\Users\Test\TestCase\Social\Mapper; -use CakeDC\Users\Auth\Social\Mapper\Facebook; +use CakeDC\Users\Social\Mapper\Facebook; use Cake\TestSuite\TestCase; class FacebookTest extends TestCase diff --git a/tests/TestCase/Auth/Social/Mapper/GoogleTest.php b/tests/TestCase/Social/Mapper/GoogleTest.php similarity index 95% rename from tests/TestCase/Auth/Social/Mapper/GoogleTest.php rename to tests/TestCase/Social/Mapper/GoogleTest.php index 376e8273a..4214a0d5d 100644 --- a/tests/TestCase/Auth/Social/Mapper/GoogleTest.php +++ b/tests/TestCase/Social/Mapper/GoogleTest.php @@ -9,9 +9,9 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Test\TestCase\Auth\Social\Mapper; +namespace CakeDC\Users\Test\TestCase\Social\Mapper; -use CakeDC\Users\Auth\Social\Mapper\Google; +use CakeDC\Users\Social\Mapper\Google; use Cake\TestSuite\TestCase; class GoogleTest extends TestCase diff --git a/tests/TestCase/Auth/Social/Mapper/InstagramTest.php b/tests/TestCase/Social/Mapper/InstagramTest.php similarity index 94% rename from tests/TestCase/Auth/Social/Mapper/InstagramTest.php rename to tests/TestCase/Social/Mapper/InstagramTest.php index 7d3b05625..616201ede 100644 --- a/tests/TestCase/Auth/Social/Mapper/InstagramTest.php +++ b/tests/TestCase/Social/Mapper/InstagramTest.php @@ -9,9 +9,9 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Test\TestCase\Auth\Social\Mapper; +namespace CakeDC\Users\Test\TestCase\Social\Mapper; -use CakeDC\Users\Auth\Social\Mapper\Instagram; +use CakeDC\Users\Social\Mapper\Instagram; use Cake\TestSuite\TestCase; class InstagramTest extends TestCase diff --git a/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php b/tests/TestCase/Social/Mapper/LinkedInTest.php similarity index 95% rename from tests/TestCase/Auth/Social/Mapper/LinkedInTest.php rename to tests/TestCase/Social/Mapper/LinkedInTest.php index 3f17e77a7..1273c8356 100644 --- a/tests/TestCase/Auth/Social/Mapper/LinkedInTest.php +++ b/tests/TestCase/Social/Mapper/LinkedInTest.php @@ -9,9 +9,9 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Test\TestCase\Auth\Social\Mapper; +namespace CakeDC\Users\Test\TestCase\Social\Mapper; -use CakeDC\Users\Auth\Social\Mapper\LinkedIn; +use CakeDC\Users\Social\Mapper\LinkedIn; use Cake\TestSuite\TestCase; class LinkedInTest extends TestCase diff --git a/tests/TestCase/Auth/Social/Mapper/TwitterTest.php b/tests/TestCase/Social/Mapper/TwitterTest.php similarity index 94% rename from tests/TestCase/Auth/Social/Mapper/TwitterTest.php rename to tests/TestCase/Social/Mapper/TwitterTest.php index d33aa343f..db75b721d 100644 --- a/tests/TestCase/Auth/Social/Mapper/TwitterTest.php +++ b/tests/TestCase/Social/Mapper/TwitterTest.php @@ -9,9 +9,9 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Test\TestCase\Auth\Social\Mapper; +namespace CakeDC\Users\Test\TestCase\Social\Mapper; -use CakeDC\Users\Auth\Social\Mapper\Twitter; +use CakeDC\Users\Social\Mapper\Twitter; use Cake\TestSuite\TestCase; class TwitterTest extends TestCase diff --git a/tests/TestCase/Social/ProviderConfigTest.php b/tests/TestCase/Social/ProviderConfigTest.php index a0a8e5c8e..93ad3c74d 100644 --- a/tests/TestCase/Social/ProviderConfigTest.php +++ b/tests/TestCase/Social/ProviderConfigTest.php @@ -62,7 +62,7 @@ public function testWithInvalidMapperClass() { Configure::write('OAuth.providers.facebook.options.clientId', '10003030300303'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'secretpassword'); - Configure::write('OAuth.providers.facebook.mapper', 'CakeDC\Users\Auth\Social\Mapper\InvalidFacebook'); + Configure::write('OAuth.providers.facebook.mapper', 'CakeDC\Users\Social\Mapper\InvalidFacebook'); $this->expectException(InvalidProviderException::class); new ProviderConfig(); @@ -87,7 +87,7 @@ public function testWithInvalidOptionsValueType() 'facebook' => [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => 'invalid options' ], ] @@ -132,7 +132,7 @@ public function testWithCustomConfig() $expected = [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'customOption' => 'hello', 'graphApiVersion' => 'v2.8', @@ -174,7 +174,7 @@ public function testWithProvidersEnabled() $expected = [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'graphApiVersion' => 'v2.8', 'redirectUri' => '/auth/facebook', @@ -200,7 +200,7 @@ public function testWithProvidersEnabled() $expected = [ 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', 'className' => 'League\OAuth1\Client\Server\Twitter', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Twitter', + 'mapper' => 'CakeDC\Users\Social\Mapper\Twitter', 'options' => [ 'redirectUri' => '/auth/twitter', 'linkSocialUri' => '/link-social/twitter', @@ -224,7 +224,7 @@ public function testWithProvidersEnabled() $expected = [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'Luchianenco\OAuth2\Client\Provider\Amazon', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Amazon', + 'mapper' => 'CakeDC\Users\Social\Mapper\Amazon', 'options' => [ 'redirectUri' => '/auth/amazon', 'linkSocialUri' => '/link-social/amazon', diff --git a/tests/TestCase/Social/Service/OAuth1ServiceTest.php b/tests/TestCase/Social/Service/OAuth1ServiceTest.php index 1ef376069..1bc84c36d 100644 --- a/tests/TestCase/Social/Service/OAuth1ServiceTest.php +++ b/tests/TestCase/Social/Service/OAuth1ServiceTest.php @@ -15,7 +15,7 @@ use Cake\Core\Configure; use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; -use Cake\Network\Session; +use Cake\Http\Session; use Cake\TestSuite\TestCase; use CakeDC\Users\Social\Service\OAuth1Service; use CakeDC\Users\Social\Service\ServiceInterface; @@ -67,7 +67,7 @@ public function setUp() $config = [ 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', 'className' => $this->Provider, - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Twitter', + 'mapper' => 'CakeDC\Users\Social\Mapper\Twitter', 'options' => [], 'collaborators' => [], 'signature' => null, @@ -107,7 +107,7 @@ public function testConstruct() $service = new OAuth1Service([ 'className' => 'League\OAuth1\Client\Server\Twitter', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Twitter', + 'mapper' => 'CakeDC\Users\Social\Mapper\Twitter', 'options' => [ 'redirectUri' => '/auth/twitter', 'linkSocialUri' => '/link-social/twitter', diff --git a/tests/TestCase/Social/Service/OAuth2ServiceTest.php b/tests/TestCase/Social/Service/OAuth2ServiceTest.php index eeda7b3bf..3859267de 100644 --- a/tests/TestCase/Social/Service/OAuth2ServiceTest.php +++ b/tests/TestCase/Social/Service/OAuth2ServiceTest.php @@ -59,7 +59,7 @@ public function setUp() $config = [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => $this->Provider, - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__' ], @@ -101,7 +101,7 @@ public function testConstruct() $service = new OAuth2Service([ 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'customOption' => 'hello', 'graphApiVersion' => 'v2.8', diff --git a/tests/TestCase/Social/Service/ServiceFactoryTest.php b/tests/TestCase/Social/Service/ServiceFactoryTest.php index d45e94c25..169e2aa07 100644 --- a/tests/TestCase/Social/Service/ServiceFactoryTest.php +++ b/tests/TestCase/Social/Service/ServiceFactoryTest.php @@ -41,7 +41,7 @@ public function testCreateFromRequest() $config = [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__', 'graphApiVersion' => 'v2.8', @@ -82,7 +82,7 @@ public function testCreateFromRequest() $expected = [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__', 'graphApiVersion' => 'v2.8', @@ -114,7 +114,7 @@ public function testCreateFromRequestCustomRedirectUriField() $config = [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__', 'graphApiVersion' => 'v2.8', @@ -156,7 +156,7 @@ public function testCreateFromRequestCustomRedirectUriField() $expected = [ 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__', 'graphApiVersion' => 'v2.8', @@ -188,7 +188,7 @@ public function testCreateFromRequestOAuth1() $config = [ 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', 'className' => 'League\OAuth1\Client\Server\Twitter', - 'mapper' => 'CakeDC\Users\Auth\Social\Mapper\Twitter', + 'mapper' => 'CakeDC\Users\Social\Mapper\Twitter', 'options' => [ 'redirectUri' => '/auth/twitter', 'linkSocialUri' => '/link-social/twitter', From bcda72d4a42f96eab6f9dc94ed7760cd9f7d06b0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 28 Jul 2018 14:44:58 -0300 Subject: [PATCH 063/685] fixed deprecated method --- tests/TestCase/Controller/SocialAccountsControllerTest.php | 1 - tests/TestCase/Middleware/SocialEmailMiddlewareTest.php | 2 +- tests/TestCase/Social/Service/OAuth2ServiceTest.php | 4 ++-- tests/TestCase/Social/Service/ServiceFactoryTest.php | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index 296f15f2f..22f247989 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -18,7 +18,6 @@ use Cake\Event\EventManager; use Cake\Http\ServerRequest; use Cake\Mailer\Email; -use Cake\Network\Request; use Cake\TestSuite\TestCase; class SocialAccountsControllerTest extends TestCase diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index 2556d5174..f4ebf0eb6 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -3,9 +3,9 @@ namespace CakeDC\Users\Test\TestCase\Middleware; use Cake\Core\Configure; +use Cake\Http\Exception\NotFoundException; use Cake\Http\Response; use Cake\Http\ServerRequestFactory; -use Cake\Network\Exception\NotFoundException; use Cake\TestSuite\TestCase; use CakeDC\Users\Social\Mapper\Facebook; use CakeDC\Users\Middleware\SocialEmailMiddleware; diff --git a/tests/TestCase/Social/Service/OAuth2ServiceTest.php b/tests/TestCase/Social/Service/OAuth2ServiceTest.php index 3859267de..553756d0a 100644 --- a/tests/TestCase/Social/Service/OAuth2ServiceTest.php +++ b/tests/TestCase/Social/Service/OAuth2ServiceTest.php @@ -3,10 +3,10 @@ namespace CakeDC\Users\Test\TestCase\Social\Service; use Cake\Core\Configure; +use Cake\Http\Exception\BadRequestException; use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; -use Cake\Network\Exception\BadRequestException; -use Cake\Network\Session; +use Cake\Http\Session; use Cake\TestSuite\TestCase; use CakeDC\Users\Social\Service\OAuth2Service; use CakeDC\Users\Social\Service\ServiceInterface; diff --git a/tests/TestCase/Social/Service/ServiceFactoryTest.php b/tests/TestCase/Social/Service/ServiceFactoryTest.php index 169e2aa07..5af9a45d7 100644 --- a/tests/TestCase/Social/Service/ServiceFactoryTest.php +++ b/tests/TestCase/Social/Service/ServiceFactoryTest.php @@ -3,8 +3,8 @@ namespace CakeDC\Users\Test\TestCase\Social\Service; use Cake\Core\Configure; +use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequestFactory; -use Cake\Network\Exception\NotFoundException; use Cake\TestSuite\TestCase; use CakeDC\Users\Social\Service\OAuth1Service; use CakeDC\Users\Social\Service\OAuth2Service; From 312707e6e792cd3eba88cc14fe0d2f18b0d014ee Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 28 Jul 2018 14:57:14 -0300 Subject: [PATCH 064/685] removed unused imports --- config/bootstrap.php | 4 ---- config/routes.php | 1 - config/users.php | 2 +- .../Component/GoogleAuthenticatorComponentTest.php | 9 --------- .../TestCase/Controller/SocialAccountsControllerTest.php | 4 ---- .../TestCase/Controller/Traits/GoogleVerifyTraitTest.php | 9 --------- tests/TestCase/Controller/Traits/LoginTraitTest.php | 9 --------- .../Controller/Traits/PasswordManagementTraitTest.php | 1 - tests/TestCase/Controller/Traits/ProfileTraitTest.php | 4 ---- tests/TestCase/Controller/Traits/RegisterTraitTest.php | 4 ---- tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php | 3 --- tests/TestCase/Controller/Traits/SocialTraitTest.php | 2 -- .../Controller/Traits/UserValidationTraitTest.php | 3 --- tests/TestCase/Mailer/UsersMailerTest.php | 2 -- tests/TestCase/Middleware/SocialAuthMiddlewareTest.php | 3 --- tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php | 5 ----- tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php | 1 - .../Model/Behavior/SocialAccountBehaviorTest.php | 3 --- tests/TestCase/Model/Table/SocialAccountsTableTest.php | 5 ----- tests/TestCase/Model/Table/UsersTableTest.php | 5 ----- tests/TestCase/Policy/RbacPolicyTest.php | 1 - tests/TestCase/View/Helper/AuthLinkHelperTest.php | 3 --- tests/TestCase/View/Helper/UserHelperTest.php | 7 ------- 23 files changed, 1 insertion(+), 89 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index 606b5f220..e0bbb3cae 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -10,10 +10,6 @@ */ use Cake\Core\Configure; -use Cake\Core\Exception\MissingPluginException; -use Cake\Core\Plugin; -use Cake\Event\EventManager; -use Cake\Log\Log; use Cake\ORM\TableRegistry; use Cake\Routing\Router; diff --git a/config/routes.php b/config/routes.php index 8c8b889ba..c843f94ab 100644 --- a/config/routes.php +++ b/config/routes.php @@ -11,7 +11,6 @@ use Cake\Core\Configure; use Cake\Routing\RouteBuilder; use Cake\Routing\Router; -use CakeDC\Users\Middleware\SocialAuthMiddleware; Router::plugin('CakeDC/Users', ['path' => '/users'], function (RouteBuilder $routes) { $routes->fallbacks('DashedRoute'); diff --git a/config/users.php b/config/users.php index ed62ccc6f..3766925a4 100644 --- a/config/users.php +++ b/config/users.php @@ -9,7 +9,7 @@ * @copyright Copyright 2010 - 2017, Cake Development Corporation (https://www.cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -use Cake\Core\Configure; + use Cake\Routing\Router; $config = [ diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index e10545f8d..3252a6d60 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -12,17 +12,8 @@ namespace CakeDC\Users\Test\TestCase\Controller\Component; use CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent; -use CakeDC\Users\Exception\MissingEmailException; -use CakeDC\Users\Exception\UserNotFoundException; use Cake\Controller\Controller; use Cake\Core\Configure; -use Cake\Core\Plugin; -use Cake\Database\Exception; -use Cake\Event\Event; -use Cake\Http\Session; -use Cake\Network\Request; -use Cake\ORM\Entity; -use Cake\Routing\Exception\MissingRouteException; use Cake\Routing\Router; use Cake\TestSuite\TestCase; use Cake\Utility\Security; diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index 22f247989..19259ec5c 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -11,11 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Controller; -use CakeDC\Users\Controller\SocialAccountsController; -use CakeDC\Users\Model\Behavior\SocialAccountBehavior; -use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Core\Configure; -use Cake\Event\EventManager; use Cake\Http\ServerRequest; use Cake\Mailer\Email; use Cake\TestSuite\TestCase; diff --git a/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php b/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php index 437e181d9..e279da5fe 100644 --- a/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php +++ b/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php @@ -15,17 +15,8 @@ use CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Controller\Traits\GoogleVerify; -use CakeDC\Users\Exception\AccountNotActiveException; -use CakeDC\Users\Exception\MissingEmailException; -use CakeDC\Users\Exception\UserNotActiveException; -use Cake\Controller\Controller; use Cake\Core\Configure; -use Cake\Event\Event; use Cake\Http\ServerRequest; -use Cake\Network\Request; -use Cake\ORM\Entity; -use Cake\TestSuite\TestCase; -use CakeDC\Users\Middleware\SocialAuthMiddleware; class GoogleVerifyTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index edac1e471..524f04775 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -11,19 +11,10 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent; use CakeDC\Users\Controller\Component\UsersAuthComponent; -use CakeDC\Users\Controller\Traits\LoginTrait; -use CakeDC\Users\Exception\AccountNotActiveException; -use CakeDC\Users\Exception\MissingEmailException; -use CakeDC\Users\Exception\UserNotActiveException; -use Cake\Controller\Controller; -use Cake\Core\Configure; use Cake\Event\Event; use Cake\Http\ServerRequest; -use Cake\Network\Request; use Cake\ORM\Entity; -use Cake\TestSuite\TestCase; use CakeDC\Users\Middleware\SocialAuthMiddleware; class LoginTraitTest extends BaseTraitTest diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 55e6d94a8..a36b0c348 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -14,7 +14,6 @@ use Cake\Auth\PasswordHasherFactory; use Cake\Core\Configure; use Cake\Event\Event; -use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; class PasswordManagementTraitTest extends BaseTraitTest diff --git a/tests/TestCase/Controller/Traits/ProfileTraitTest.php b/tests/TestCase/Controller/Traits/ProfileTraitTest.php index 243e77fce..580906126 100644 --- a/tests/TestCase/Controller/Traits/ProfileTraitTest.php +++ b/tests/TestCase/Controller/Traits/ProfileTraitTest.php @@ -11,10 +11,6 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use CakeDC\Users\Controller\Traits\ProfileTrait; -use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; -use Cake\ORM\TableRegistry; - class ProfileTraitTest extends BaseTraitTest { /** diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 0c020f007..161871592 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -11,12 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; use Cake\Core\Configure; -use Cake\Core\Plugin; use Cake\Event\Event; -use Cake\Mailer\Email; -use Cake\ORM\TableRegistry; class RegisterTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php index be5358db3..04ed9cc18 100644 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -11,9 +11,6 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; -use Cake\Network\Request; - class SimpleCrudTraitTest extends BaseTraitTest { public $viewVars; diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index f73dbaee1..870cda9a0 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -11,10 +11,8 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use Cake\Core\Configure; use Cake\Http\Response; use Cake\Http\ServerRequest; -use Cake\TestSuite\TestCase; use CakeDC\Users\Middleware\SocialAuthMiddleware; class SocialTraitTest extends BaseTraitTest diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index db475020b..95c04a6d1 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -11,9 +11,6 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; -use Cake\Network\Request; - class UserValidationTraitTest extends BaseTraitTest { /** diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index ae79ca496..ec9c46331 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -10,9 +10,7 @@ */ namespace CakeDC\Users\Test\TestCase\Email; -use Cake\Mailer\Email; use Cake\ORM\TableRegistry; -use Cake\Routing\Router; use Cake\TestSuite\TestCase; /** diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index d40b6ac7c..7c41539de 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -11,12 +11,9 @@ use Cake\Core\Configure; use Cake\Http\Response; use Cake\Http\ServerRequestFactory; -use Cake\Routing\Router; use Cake\TestSuite\TestCase; -use CakeDC\Users\Social\Mapper\Facebook; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Model\Entity\User; -use CakeDC\Users\Social\Service\OAuth2Service; use League\OAuth2\Client\Provider\FacebookUser; use Zend\Diactoros\Uri; diff --git a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php index 2134da7eb..bd83825f9 100644 --- a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php @@ -11,15 +11,10 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; -use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Model\Behavior\AuthFinderBehavior; -use CakeDC\Users\Model\Table\UsersTable; -use Cake\Mailer\Email; use Cake\ORM\TableRegistry; -use Cake\Routing\Router; use Cake\TestSuite\TestCase; use Cake\Utility\Hash; -use InvalidArgumentException; /** * Test Case diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php index 0d2710ae0..4ba37e373 100644 --- a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php @@ -12,7 +12,6 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; use CakeDC\Users\Model\Behavior\LinkSocialBehavior; -use CakeDC\Users\Model\Table\UsersTable; use Cake\I18n\Time; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; diff --git a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php index b9149c516..d67d8628d 100644 --- a/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialAccountBehaviorTest.php @@ -13,11 +13,8 @@ use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Event\Event; -use Cake\Mailer\Email; use Cake\ORM\TableRegistry; -use Cake\Routing\Router; use Cake\TestSuite\TestCase; -use InvalidArgumentException; /** * Test Case diff --git a/tests/TestCase/Model/Table/SocialAccountsTableTest.php b/tests/TestCase/Model/Table/SocialAccountsTableTest.php index f662d7bf2..5ab1c2493 100644 --- a/tests/TestCase/Model/Table/SocialAccountsTableTest.php +++ b/tests/TestCase/Model/Table/SocialAccountsTableTest.php @@ -11,12 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Model\Table; -use CakeDC\Users\Model\Table\SocialAccountsTable; -use CakeDC\Users\Model\Table\UsersTable; -use Cake\Event\Event; -use Cake\Mailer\Email; use Cake\ORM\TableRegistry; -use Cake\Routing\Router; use Cake\TestSuite\TestCase; /** diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 03b91b37e..abd5493b7 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -11,16 +11,11 @@ namespace CakeDC\Users\Test\TestCase\Model\Table; -use CakeDC\Users\Exception\AccountNotActiveException; -use CakeDC\Users\Exception\UserAlreadyActiveException; -use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Model\Table\SocialAccountsTable; -use Cake\Core\Plugin; use Cake\Mailer\Email; use Cake\ORM\TableRegistry; use Cake\Routing\Router; use Cake\TestSuite\TestCase; -use Cake\Utility\Hash; use InvalidArgumentException; /** diff --git a/tests/TestCase/Policy/RbacPolicyTest.php b/tests/TestCase/Policy/RbacPolicyTest.php index bd1ceb095..c45ef89b3 100644 --- a/tests/TestCase/Policy/RbacPolicyTest.php +++ b/tests/TestCase/Policy/RbacPolicyTest.php @@ -3,7 +3,6 @@ namespace CakeDC\Users\Test\TestCase\Policy; use Authentication\Identity; -use Authorization\Policy\BeforePolicyInterface; use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; use CakeDC\Auth\Rbac\Rbac; diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php index 03558651e..9a0ace80c 100644 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -15,9 +15,6 @@ use CakeDC\Auth\Rbac\Rbac; use CakeDC\Users\Model\Entity\User; use CakeDC\Users\View\Helper\AuthLinkHelper; -use CakeDC\Users\View\Helper\UserHelper; -use Cake\Event\Event; -use Cake\Event\EventManager; use Cake\TestSuite\TestCase; use Cake\View\View; diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 481087adb..2ac78b3a1 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -13,17 +13,10 @@ use CakeDC\Users\Model\Entity\SocialAccount; use CakeDC\Users\View\Helper\UserHelper; -use Cake\Core\App; use Cake\Core\Configure; -use Cake\Core\Plugin; -use Cake\Event\Event; use Cake\Http\ServerRequest; use Cake\I18n\I18n; -use Cake\Network\Request; -use Cake\Routing\Router; use Cake\TestSuite\TestCase; -use Cake\View\Helper\HtmlHelper; -use Cake\View\View; /** * Users\View\Helper\UserHelper Test Case From 09d03fe2377faca5c4e7202f7066ad6ddfaa3770 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 28 Jul 2018 15:08:46 -0300 Subject: [PATCH 065/685] fixed unused local variable --- .../Traits/GoogleVerifyTraitTest.php | 2 -- .../Controller/Traits/LinkSocialTraitTest.php | 3 --- .../Controller/Traits/LoginTraitTest.php | 2 -- .../Controller/Traits/RecaptchaTraitTest.php | 20 ++++++++++++++++++- .../Model/Behavior/AuthFinderBehaviorTest.php | 2 +- .../Model/Behavior/LinkSocialBehaviorTest.php | 5 +---- .../Model/Behavior/PasswordBehaviorTest.php | 5 ++++- .../Model/Behavior/RegisterBehaviorTest.php | 2 +- tests/TestCase/PluginTest.php | 10 ++++++++++ 9 files changed, 36 insertions(+), 15 deletions(-) diff --git a/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php b/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php index e279da5fe..0baa0f823 100644 --- a/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php +++ b/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php @@ -84,7 +84,6 @@ public function testVerifyHappy() */ public function testVerifyNotEnabled() { - $loginAction = Configure::read('Auth.AuthenticationComponent.loginAction'); $this->_mockFlash(); Configure::write('Users.GoogleAuthenticator.login', false); $this->Trait->Flash->expects($this->once()) @@ -95,7 +94,6 @@ public function testVerifyNotEnabled() ->with($this->loginPage); $this->Trait->verify(); - } /** diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 2220849cc..a17061118 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -283,7 +283,6 @@ public function testCallbackLinkSocialHappy() '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')); @@ -488,8 +487,6 @@ public function testCallbackLinkSocialUnknownProvider() Configure::write('OAuth.providers.facebook.options.clientId', 'testclientidtestclientid'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'testclientsecrettestclientsecret'); - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $this->Provider->expects($this->never()) ->method('getAuthorizationUrl'); diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 524f04775..c5ea44da5 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -197,7 +197,6 @@ public function testFailedSocialUserNotActive() */ public function testFailedSocialUserAccountNotActive() { - $event = new Entity(); $data = [ 'id' => 111111, 'username' => 'user-1' @@ -222,7 +221,6 @@ public function testFailedSocialUserAccountNotActive() */ public function testFailedSocialUserAccount() { - $event = new Entity(); $data = [ 'id' => 111111, 'username' => 'user-1' diff --git a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php index a72250221..c05f5a353 100644 --- a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php +++ b/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php @@ -117,7 +117,25 @@ public function testGetRecaptchaInstanceNull() public function testValidateReCaptchaFalse() { - $trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\ReCaptchaTrait')->getMockForTrait(); + $ReCaptcha = $this->getMockBuilder('ReCaptcha\ReCaptcha') + ->setMethods(['verify']) + ->disableOriginalConstructor() + ->getMock(); + $Response = $this->getMockBuilder('ReCaptcha\Response') + ->setMethods(['isSuccess']) + ->disableOriginalConstructor() + ->getMock(); + $Response->expects($this->once()) + ->method('isSuccess') + ->will($this->returnValue(false)); + $ReCaptcha->expects($this->once()) + ->method('verify') + ->with('value') + ->will($this->returnValue($Response)); + $this->Trait->expects($this->once()) + ->method('_getReCaptchaInstance') + ->will($this->returnValue($ReCaptcha)); + $this->assertFalse($this->Trait->validateReCaptcha('value', '255.255.255.255')); } } diff --git a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php index bd83825f9..44326db21 100644 --- a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php @@ -73,7 +73,7 @@ public function testFindActive() */ public function testFindAuthBadMethodCallException() { - $user = $this->table->find('auth'); + $this->table->find('auth'); } /** diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php index 4ba37e373..56669325c 100644 --- a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php @@ -185,9 +185,6 @@ public function testlinkSocialAccountErrorSavingFacebookProvider($data, $userId, ] ]; $this->assertEquals($expected, $actual); - - $error = $user->getErrors('social_accounts'); - $error = $error ? reset($error) : $message; } /** @@ -277,7 +274,7 @@ public function testlinkSocialAccountFacebookProviderAccountExists($data, $userI $this->assertEquals($expected, $actual); //Se for o usuário que já esta associado então okay - $socialAccount = $this->Table->SocialAccounts->find()->where([ + $this->Table->SocialAccounts->find()->where([ 'reference' => $data['id'], 'provider' => $data['provider'] ])->firstOrFail(); diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 5ba5a7950..34013b3a1 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; use CakeDC\Users\Model\Behavior\PasswordBehavior; +use CakeDC\Users\Model\Entity\User; use CakeDC\Users\Test\App\Mailer\OverrideMailer; use Cake\Core\Configure; use Cake\Mailer\Email; @@ -172,7 +173,7 @@ public function testResetTokenUserAlreadyActive() */ public function testResetTokenUserNotActive() { - $user = $this->table->findByUsername('user-1')->first(); + $this->table->findByUsername('user-1')->firstOrFail(); $this->Behavior->resetToken('user-1', [ 'ensureActive' => true, 'expiration' => 3600 @@ -203,6 +204,8 @@ public function testChangePassword() $user->password_confirmation = 'new'; $result = $this->Behavior->changePassword($user); + $this->assertInstanceOf(User::class, $result); + $this->assertEmpty($result->getErrors()); } /** diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index d1dbcee6e..b01ac12af 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -363,6 +363,6 @@ public function testResendValidationEmailThrows() $result = $this->Table->register($this->Table->newEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); $activeUser = $this->Table->activateUser($result); $this->expectException(UserAlreadyActiveException::class); - $updatedResult = $this->Table->resendValidationEmail($activeUser, ['token_expiration' => 4000]); + $this->Table->resendValidationEmail($activeUser, ['token_expiration' => 4000]); } } diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 2dced5856..0e01e474a 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -279,6 +279,11 @@ public function testGetAuthenticationService() 'skipGoogleVerify' => true ] ]; + $actual = []; + foreach ($authenticators as $key => $value) { + $actual[get_class($value)] = $value->getConfig(); + } + $this->assertEquals($expected, $actual); /** * @var \Authentication\Authenticator\AuthenticatorCollection $authenticators @@ -373,6 +378,11 @@ public function testGetAuthenticationServiceWithouGoogleAuthenticator() 'skipGoogleVerify' => true ] ]; + $actual = []; + foreach ($authenticators as $key => $value) { + $actual[get_class($value)] = $value->getConfig(); + } + $this->assertEquals($expected, $actual); } /** From fc5f239a5ee9ebe7cb17065e4b9c0057e8221c10 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 28 Jul 2018 15:10:54 -0300 Subject: [PATCH 066/685] fixed 'unused parameters' --- tests/TestCase/Middleware/SocialAuthMiddlewareTest.php | 2 +- tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index 7c41539de..5dc667c34 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -129,7 +129,7 @@ public function testProceedStepOne() $Middleware = new SocialAuthMiddleware(); $response = new Response(); - $next = function ($request, $response) { + $next = function () { $this->fail('Should not call $next'); }; diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php index 56669325c..99ccee2e8 100644 --- a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php @@ -159,13 +159,12 @@ public function providerFacebookLinkSocialAccount() * * @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) + public function testlinkSocialAccountErrorSavingFacebookProvider($data, $userId) { $user = $this->Table->get($userId); $resultUser = $this->Behavior->linkSocialAccount($user, $data); From 6af9da160ff3c127fc91106104497b710dd32b16 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 28 Jul 2018 15:21:25 -0300 Subject: [PATCH 067/685] redirect user to login page when not authorized --- config/users.php | 1 + 1 file changed, 1 insertion(+) diff --git a/config/users.php b/config/users.php index 3766925a4..ffda7efda 100644 --- a/config/users.php +++ b/config/users.php @@ -171,6 +171,7 @@ 'unauthorizedHandler' => [ 'exceptions' => [ 'MissingIdentityException' => 'Authorization\Exception\MissingIdentityException', + 'ForbiddenException' => 'Authorization\Exception\ForbiddenException', ], 'className' => 'Authorization.CakeRedirect', 'url' => [ From 7fe3003421bff88456ce89344fe41b199628108e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 28 Jul 2018 16:12:34 -0300 Subject: [PATCH 068/685] phpcs fixes --- composer.json | 15 +++++++++--- src/Authentication/AuthenticationService.php | 6 ++--- .../AuthenticatorFeedbackInterface.php | 4 +--- src/Authenticator/CookieAuthenticator.php | 3 +-- src/Authenticator/FormAuthenticator.php | 10 ++++---- .../GoogleTwoFactorAuthenticator.php | 1 - src/Controller/Traits/GoogleVerifyTrait.php | 2 +- src/Controller/Traits/LinkSocialTrait.php | 2 +- src/Controller/Traits/LoginTrait.php | 3 +-- .../Traits/PasswordManagementTrait.php | 4 ++-- src/Controller/Traits/RegisterTrait.php | 4 ++-- src/Controller/Traits/SocialTrait.php | 2 +- .../GoogleAuthenticatorMiddleware.php | 5 ++-- src/Middleware/SocialAuthMiddleware.php | 15 ++++++------ src/Middleware/SocialEmailMiddleware.php | 13 +++++----- src/Model/Behavior/SocialAccountBehavior.php | 1 - src/Plugin.php | 18 +++++++------- src/Policy/RbacPolicy.php | 4 ++-- src/Social/Locator/DatabaseLocator.php | 11 ++++----- src/Social/Locator/LocatorInterface.php | 3 +-- src/Social/ProviderConfig.php | 11 ++++----- src/Social/Service/OAuth2Service.php | 3 +-- src/Social/Service/OAuthServiceAbstract.php | 10 +++++--- src/Social/Service/ServiceFactory.php | 6 ++--- src/Social/Service/ServiceInterface.php | 4 +--- src/Template/Users/edit.ctp | 1 + src/Template/Users/register.ctp | 1 + src/Traits/IsAuthorizedTrait.php | 7 +++--- src/View/Helper/AuthLinkHelper.php | 2 +- .../AuthenticationServiceTest.php | 5 ++-- .../Authenticator/FormAuthenticatorTest.php | 6 +---- .../Controller/Traits/BaseTraitTest.php | 7 +++--- .../Traits/GoogleVerifyTraitTest.php | 4 ++-- .../Controller/Traits/LinkSocialTraitTest.php | 24 +++++++++---------- .../Controller/Traits/LoginTraitTest.php | 3 +-- .../Controller/Traits/SocialTraitTest.php | 2 +- .../Middleware/SocialAuthMiddlewareTest.php | 16 ++++++------- .../Middleware/SocialEmailMiddlewareTest.php | 24 +++++++++---------- tests/TestCase/PluginTest.php | 9 ++++--- tests/TestCase/Policy/RbacPolicyTest.php | 4 ++-- .../Social/Locator/DatabaseLocatorTest.php | 7 +++--- tests/TestCase/Social/ProviderConfigTest.php | 7 +++--- .../Social/Service/OAuth1ServiceTest.php | 13 +++------- .../Social/Service/OAuth2ServiceTest.php | 17 ++++--------- .../Social/Service/ServiceFactoryTest.php | 6 ++--- 45 files changed, 147 insertions(+), 178 deletions(-) diff --git a/composer.json b/composer.json index ad2cca5c7..baf055643 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,6 @@ }, "require-dev": { "phpunit/phpunit": "^5.0", - "cakephp/cakephp-codesniffer": "^2.0", "league/oauth2-facebook": "@stable", "league/oauth2-instagram": "@stable", "league/oauth2-google": "@stable", @@ -43,7 +42,8 @@ "satooshi/php-coveralls": "^2.0", "league/oauth1-client": "^1.7", "cakephp/authentication": "^1.0@RC", - "cakephp/authorization": "^1.0@beta" + "cakephp/authorization": "^1.0@beta", + "cakephp/cakephp-codesniffer": "^3.0" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", @@ -67,5 +67,14 @@ } }, "minimum-stability": "dev", - "prefer-stable": true + "prefer-stable": true, + "scripts": { + "check": [ + "@test", + "@cs-check" + ], + "cs-check": "vendor/bin/phpcs -n --colors -p --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests", + "cs-fix": "vendor/bin/phpcbf --colors --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests", + "test": "vendor/bin/phpunit --colors=always ./tests" + } } diff --git a/src/Authentication/AuthenticationService.php b/src/Authentication/AuthenticationService.php index eb8fc291d..2b49d15de 100644 --- a/src/Authentication/AuthenticationService.php +++ b/src/Authentication/AuthenticationService.php @@ -2,7 +2,7 @@ namespace CakeDC\Users\Authentication; -use \Authentication\AuthenticationService as BaseService; +use Authentication\AuthenticationService as BaseService; use Authentication\Authenticator\Result; use Authentication\Authenticator\ResultInterface; use Authentication\Authenticator\StatelessInterface; @@ -21,6 +21,7 @@ class AuthenticationService extends BaseService * @param ServerRequestInterface $request response to manipulate * @param ResponseInterface $response base response to manipulate * @param ResultInterface $result valid result + * @return array with result, request and response keys */ protected function proceedToGoogleVerify(ServerRequestInterface $request, ResponseInterface $response, ResultInterface $result) { @@ -88,5 +89,4 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface 'response' => $response ]; } - -} \ No newline at end of file +} diff --git a/src/Authenticator/AuthenticatorFeedbackInterface.php b/src/Authenticator/AuthenticatorFeedbackInterface.php index 54a441f1e..21f174213 100644 --- a/src/Authenticator/AuthenticatorFeedbackInterface.php +++ b/src/Authenticator/AuthenticatorFeedbackInterface.php @@ -2,7 +2,6 @@ namespace CakeDC\Users\Authenticator; - use Authentication\Authenticator\Result; interface AuthenticatorFeedbackInterface @@ -13,5 +12,4 @@ interface AuthenticatorFeedbackInterface * @return Result|null */ public function getLastResult(); - -} \ No newline at end of file +} diff --git a/src/Authenticator/CookieAuthenticator.php b/src/Authenticator/CookieAuthenticator.php index 82777ce1f..c16cc4f17 100644 --- a/src/Authenticator/CookieAuthenticator.php +++ b/src/Authenticator/CookieAuthenticator.php @@ -2,12 +2,11 @@ namespace CakeDC\Users\Authenticator; +use Authentication\Authenticator\CookieAuthenticator as BaseAuthenticator; use Authentication\Authenticator\PersistenceInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use Authentication\Authenticator\CookieAuthenticator as BaseAuthenticator; - /** * Cookie Authenticator * diff --git a/src/Authenticator/FormAuthenticator.php b/src/Authenticator/FormAuthenticator.php index 56a759840..bd23074f7 100644 --- a/src/Authenticator/FormAuthenticator.php +++ b/src/Authenticator/FormAuthenticator.php @@ -6,8 +6,8 @@ use Authentication\Authenticator\FormAuthenticator as BaseFormAuthenticator; use Authentication\Authenticator\Result; use Authentication\Identifier\IdentifierInterface; -use Cake\Core\Configure; use CakeDC\Users\Controller\Traits\ReCaptchaTrait; +use Cake\Core\Configure; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -113,7 +113,7 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface $data = $request->getParsedBody(); $captcha = $data['g-recaptcha-response'] ? $data['g-recaptcha-response'] : null; - $valid = $this->validateReCaptcha( + $valid = $this->validateReCaptcha( $captcha, $request->clientIp() ); @@ -128,12 +128,12 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface /** * Call base authenticator methods * - * @param string $name - * @param array $arguments + * @param string $name base authentication method name + * @param array $arguments used in base authenticator method * @return mixed */ public function __call($name, $arguments) { return $this->getBaseAuthenticator()->$name(...$arguments); } -} \ No newline at end of file +} diff --git a/src/Authenticator/GoogleTwoFactorAuthenticator.php b/src/Authenticator/GoogleTwoFactorAuthenticator.php index 1b9240743..061adda8c 100644 --- a/src/Authenticator/GoogleTwoFactorAuthenticator.php +++ b/src/Authenticator/GoogleTwoFactorAuthenticator.php @@ -31,7 +31,6 @@ class GoogleTwoFactorAuthenticator extends AbstractAuthenticator 'urlChecker' => 'Authentication.Default', ]; - /** * Prepares the error object for a login URL error * diff --git a/src/Controller/Traits/GoogleVerifyTrait.php b/src/Controller/Traits/GoogleVerifyTrait.php index 2e3e79b0e..ac1a5d9fa 100644 --- a/src/Controller/Traits/GoogleVerifyTrait.php +++ b/src/Controller/Traits/GoogleVerifyTrait.php @@ -158,4 +158,4 @@ protected function onPostVerifyCodeOkay($loginAction, $user) return $this->redirect($loginAction); } -} \ No newline at end of file +} diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index ba4d16fc4..26d2f5e0c 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Utility\Hash; use CakeDC\Users\Social\Service\ServiceFactory; +use Cake\Utility\Hash; /** * Ações para "linkar" contas sociais diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 8cd814d49..987f3c14c 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -16,9 +16,9 @@ use CakeDC\Users\Authenticator\AuthenticatorFeedbackInterface; use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Middleware\SocialAuthMiddleware; +use CakeDC\Users\Plugin; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; -use CakeDC\Users\Plugin; /** * Covers the login, logout and social login @@ -64,7 +64,6 @@ public function failedSocialLogin($error, $data, $flash = false) 'Your social account has not been validated yet. Please check your inbox for instructions' ); break; - } if ($flash) { diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 6c4ad4f16..fa2135e12 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -11,13 +11,13 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Utility\Hash; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Exception\WrongPasswordException; +use CakeDC\Users\Plugin; use Cake\Core\Configure; +use Cake\Utility\Hash; use Cake\Validation\Validator; -use CakeDC\Users\Plugin; use Exception; /** diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 83cdf5ca6..1d41972ba 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -11,12 +11,12 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Utility\Hash; +use CakeDC\Users\Plugin; use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Http\Exception\NotFoundException; use Cake\Http\Response; -use CakeDC\Users\Plugin; +use Cake\Utility\Hash; /** * Covers registration features and email token validation diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 44feca3b6..7ca44427b 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Http\Exception\NotFoundException; use CakeDC\Users\Middleware\SocialAuthMiddleware; +use Cake\Http\Exception\NotFoundException; /** * Covers registration features and email token validation diff --git a/src/Middleware/GoogleAuthenticatorMiddleware.php b/src/Middleware/GoogleAuthenticatorMiddleware.php index 04aabb402..9dbf0ffd0 100644 --- a/src/Middleware/GoogleAuthenticatorMiddleware.php +++ b/src/Middleware/GoogleAuthenticatorMiddleware.php @@ -2,9 +2,9 @@ namespace CakeDC\Users\Middleware; +use CakeDC\Users\Authentication\AuthenticationService; use Cake\Http\ServerRequest; use Cake\Routing\Router; -use CakeDC\Users\Authentication\AuthenticationService; use Psr\Http\Message\ResponseInterface; class GoogleAuthenticatorMiddleware @@ -39,5 +39,4 @@ public function __invoke(ServerRequest $request, ResponseInterface $response, $n ->withHeader('Location', $url) ->withStatus(302); } - -} \ No newline at end of file +} diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 31ac6d3da..3170895c7 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -2,18 +2,18 @@ namespace CakeDC\Users\Middleware; -use Cake\Core\InstanceConfigTrait; -use Cake\Datasource\Exception\RecordNotFoundException; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; +use CakeDC\Users\Plugin; +use CakeDC\Users\Social\Locator\DatabaseLocator; +use CakeDC\Users\Social\Service\ServiceFactory; use Cake\Core\Configure; +use Cake\Core\InstanceConfigTrait; +use Cake\Datasource\Exception\RecordNotFoundException; use Cake\Event\EventDispatcherTrait; use Cake\Http\ServerRequest; use Cake\Log\LogTrait; -use CakeDC\Users\Plugin; -use CakeDC\Users\Social\Locator\DatabaseLocator; -use CakeDC\Users\Social\Service\ServiceFactory; use Psr\Http\Message\ResponseInterface; class SocialAuthMiddleware @@ -95,7 +95,6 @@ protected function finishWithResult($result, ServerRequest $request, ResponseInt * 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. */ @@ -157,7 +156,7 @@ protected function _touch(array $data) } catch (MissingEmailException $ex) { $this->authStatus = self::AUTH_ERROR_MISSING_EMAIL; $exception = $ex; - } catch(RecordNotFoundException $ex) { + } catch (RecordNotFoundException $ex) { $this->authStatus = self::AUTH_ERROR_FIND_USER; $exception = $ex; } @@ -183,4 +182,4 @@ protected function _mapUser($data) return $user; } -} \ No newline at end of file +} diff --git a/src/Middleware/SocialEmailMiddleware.php b/src/Middleware/SocialEmailMiddleware.php index 44ea2360f..7f6af585a 100644 --- a/src/Middleware/SocialEmailMiddleware.php +++ b/src/Middleware/SocialEmailMiddleware.php @@ -2,13 +2,13 @@ namespace CakeDC\Users\Middleware; -use Cake\Http\Exception\NotFoundException; use CakeDC\Users\Controller\Traits\ReCaptchaTrait; use Cake\Core\Configure; +use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequest; use Psr\Http\Message\ResponseInterface; -class SocialEmailMiddleware extends SocialAuthMiddleware +class SocialEmailMiddleware extends SocialAuthMiddleware { use ReCaptchaTrait; @@ -35,10 +35,9 @@ public function __invoke(ServerRequest $request, ResponseInterface $response, $n /** * Handle social email step post. * - * @param int $result authentication result - * @param \Psr\Http\Message\ServerRequestInterface $request The request. - * @param \Psr\Http\Message\ResponseInterface $response The response. - * @param callable $next Callback to invoke the next middleware. + * @param int $request authentication result + * @param \Psr\Http\Message\ServerRequestInterface $response The request. + * @param \Psr\Http\Message\ResponseInterface $next The response. * @return \Psr\Http\Message\ResponseInterface A response */ private function handleAction(ServerRequest $request, ResponseInterface $response, $next) @@ -103,4 +102,4 @@ protected function getUser(ServerRequest $request) return false; } -} \ No newline at end of file +} diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 1ab405ab3..cab8b653e 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -24,7 +24,6 @@ /** * Covers social account features - * */ class SocialAccountBehavior extends Behavior { diff --git a/src/Plugin.php b/src/Plugin.php index d5491dd03..360173a67 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -11,16 +11,16 @@ use Authorization\Policy\MapResolver; use Authorization\Policy\OrmResolver; use Authorization\Policy\ResolverCollection; -use Cake\Core\BasePlugin; -use Cake\Core\Configure; -use Cake\Http\MiddlewareQueue; -use Cake\Http\ServerRequest; use CakeDC\Auth\Middleware\RbacMiddleware; use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Middleware\GoogleAuthenticatorMiddleware; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; use CakeDC\Users\Policy\RbacPolicy; +use Cake\Core\BasePlugin; +use Cake\Core\Configure; +use Cake\Http\MiddlewareQueue; +use Cake\Http\ServerRequest; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -63,10 +63,10 @@ public function getAuthorizationService(ServerRequestInterface $request, Respons $map, $orm ]); + return new AuthorizationService($resolver); } - /** * load authenticators and identifiers * @@ -78,7 +78,7 @@ public function authentication() $authenticators = Configure::read('Auth.Authenticators'); $identifiers = Configure::read('Auth.Identifiers'); - foreach($identifiers as $identifier => $options) { + foreach ($identifiers as $identifier => $options) { if (is_numeric($identifier)) { $identifier = $options; $options = []; @@ -87,7 +87,7 @@ public function authentication() $service->loadIdentifier($identifier, $options); } - foreach($authenticators as $authenticator => $options) { + foreach ($authenticators as $authenticator => $options) { if (is_numeric($authenticator)) { $authenticator = $options; $options = []; @@ -131,7 +131,7 @@ public function middleware($middlewareQueue) /** * Add authorization middleware based on Auth.Authorization * - * @param MiddlewareQueue $middlewareQueue + * @param MiddlewareQueue $middlewareQueue queue of middleware * @return MiddlewareQueue */ protected function addAuthorizationMiddleware(MiddlewareQueue $middlewareQueue) @@ -159,4 +159,4 @@ protected function addAuthorizationMiddleware(MiddlewareQueue $middlewareQueue) return $middlewareQueue; } -} \ No newline at end of file +} diff --git a/src/Policy/RbacPolicy.php b/src/Policy/RbacPolicy.php index 6d53fa348..c55a48f1a 100644 --- a/src/Policy/RbacPolicy.php +++ b/src/Policy/RbacPolicy.php @@ -9,7 +9,7 @@ class RbacPolicy /** * Check rbac permission * - * @param \Authorization\IdentityInterface|null $identity + * @param \Authorization\IdentityInterface|null $identity user identity * @param ServerRequestInterface $resource server request * @return bool */ @@ -21,4 +21,4 @@ public function canAccess($identity, $resource) return (bool)$rbac->checkPermissions($user, $resource); } -} \ No newline at end of file +} diff --git a/src/Social/Locator/DatabaseLocator.php b/src/Social/Locator/DatabaseLocator.php index 35ee6f3f4..65bca084e 100644 --- a/src/Social/Locator/DatabaseLocator.php +++ b/src/Social/Locator/DatabaseLocator.php @@ -1,14 +1,14 @@ providers = $this->normalizeConfig(Hash::merge($config, $oauthConfig))['providers']; - } /** @@ -111,7 +109,7 @@ protected function _validateConfig(&$value, $key) * @param array $options array of options by provider * @return bool */ - public function _isProviderEnabled($options) + protected function _isProviderEnabled($options) { return !empty($options['options']['redirectUri']) && !empty($options['options']['clientId']) && !empty($options['options']['clientSecret']); @@ -127,5 +125,4 @@ public function getConfig($alias): array { return Hash::get($this->providers, $alias, []); } - -} \ No newline at end of file +} diff --git a/src/Social/Service/OAuth2Service.php b/src/Social/Service/OAuth2Service.php index 5e947d3bc..c7bd0d244 100644 --- a/src/Social/Service/OAuth2Service.php +++ b/src/Social/Service/OAuth2Service.php @@ -96,7 +96,6 @@ protected function validate(ServerRequest $request) return true; } - /** * Instantiates provider object. * @@ -113,4 +112,4 @@ protected function setProvider($config) $this->provider = new $class($config['options'], $config['collaborators']); } } -} \ No newline at end of file +} diff --git a/src/Social/Service/OAuthServiceAbstract.php b/src/Social/Service/OAuthServiceAbstract.php index e0545dcab..66ef99b1c 100644 --- a/src/Social/Service/OAuthServiceAbstract.php +++ b/src/Social/Service/OAuthServiceAbstract.php @@ -16,6 +16,8 @@ abstract class OAuthServiceAbstract implements ServiceInterface protected $providerName; /** + * Get the social provider name + * * @return string */ public function getProviderName(): string @@ -24,11 +26,13 @@ public function getProviderName(): string } /** - * @param string $providerName + * Set the social provider name + * + * @param string $providerName social provider + * @return void */ public function setProviderName(string $providerName) { $this->providerName = $providerName; } - -} \ No newline at end of file +} diff --git a/src/Social/Service/ServiceFactory.php b/src/Social/Service/ServiceFactory.php index 6890b1a54..fd08e9a98 100644 --- a/src/Social/Service/ServiceFactory.php +++ b/src/Social/Service/ServiceFactory.php @@ -2,9 +2,9 @@ namespace CakeDC\Users\Social\Service; +use CakeDC\Users\Social\ProviderConfig; use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequest; -use CakeDC\Users\Social\ProviderConfig; class ServiceFactory { @@ -12,7 +12,7 @@ class ServiceFactory protected $redirectUriField = 'redirectUri'; /** - * @param string $redirectUriField + * @param string $redirectUriField field used for redirect uri * * @return self */ @@ -57,4 +57,4 @@ public function createFromRequest(ServerRequest $request): ServiceInterface { return $this->createFromProvider($request->getAttribute('params')['provider'] ?? null); } -} \ No newline at end of file +} diff --git a/src/Social/Service/ServiceInterface.php b/src/Social/Service/ServiceInterface.php index a73489fb5..c3861a904 100644 --- a/src/Social/Service/ServiceInterface.php +++ b/src/Social/Service/ServiceInterface.php @@ -1,7 +1,6 @@ diff --git a/src/Traits/IsAuthorizedTrait.php b/src/Traits/IsAuthorizedTrait.php index 175d83721..75ed99129 100644 --- a/src/Traits/IsAuthorizedTrait.php +++ b/src/Traits/IsAuthorizedTrait.php @@ -2,10 +2,10 @@ namespace CakeDC\Users\Traits; +use CakeDC\Auth\Rbac\Rbac; use Cake\Http\ServerRequest; use Cake\Routing\Exception\MissingRouteException; use Cake\Routing\Router; -use CakeDC\Auth\Rbac\Rbac; use Zend\Diactoros\Uri; trait IsAuthorizedTrait @@ -60,7 +60,7 @@ protected function checkRbacPermissions($url) 'uri' => $uri ]); $params = Router::parseRequest($targetRequest); - $targetRequest = $targetRequest->withAttribute('params', $params); + $targetRequest = $targetRequest->withAttribute('params', $params); $user = $this->request->getAttribute('identity'); $userData = []; @@ -70,5 +70,4 @@ protected function checkRbacPermissions($url) return $Rbac->checkPermissions($userData, $targetRequest); } - -} \ No newline at end of file +} diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index f61655ade..d30c3b0b3 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -11,9 +11,9 @@ namespace CakeDC\Users\View\Helper; +use CakeDC\Users\Traits\IsAuthorizedTrait; use Cake\Utility\Hash; use Cake\View\Helper\HtmlHelper; -use CakeDC\Users\Traits\IsAuthorizedTrait; /** * AuthLink helper diff --git a/tests/TestCase/Authentication/AuthenticationServiceTest.php b/tests/TestCase/Authentication/AuthenticationServiceTest.php index dd4d134ce..9843ab4fe 100644 --- a/tests/TestCase/Authentication/AuthenticationServiceTest.php +++ b/tests/TestCase/Authentication/AuthenticationServiceTest.php @@ -1,13 +1,13 @@ assertEmpty($response->getHeaderLine('Location')); $this->assertNull($response->getStatusCode()); - } } diff --git a/tests/TestCase/Authenticator/FormAuthenticatorTest.php b/tests/TestCase/Authenticator/FormAuthenticatorTest.php index 8e1c7658e..b0c3f4862 100644 --- a/tests/TestCase/Authenticator/FormAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/FormAuthenticatorTest.php @@ -3,11 +3,11 @@ use Authentication\Authenticator\Result; use Authentication\Identifier\IdentifierCollection; use Authentication\Identifier\IdentifierInterface; +use CakeDC\Users\Authenticator\FormAuthenticator; use Cake\Core\Configure; use Cake\Http\Client\Response; use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; -use CakeDC\Users\Authenticator\FormAuthenticator; class FormAuthenticatorTest extends TestCase { @@ -18,7 +18,6 @@ class FormAuthenticatorTest extends TestCase */ public function testAuthenticateBaseFailed() { - $identifiers = new IdentifierCollection([ 'Authentication.Password' ]); @@ -83,7 +82,6 @@ public function testAuthenticateBaseFailed() */ public function testAuthenticate() { - $identifiers = new IdentifierCollection([ 'Authentication.Password' ]); @@ -156,7 +154,6 @@ public function testAuthenticate() */ public function testAuthenticateNotRequiredReCaptcha() { - $identifiers = new IdentifierCollection([ 'Authentication.Password' ]); @@ -225,7 +222,6 @@ public function testAuthenticateNotRequiredReCaptcha() */ public function testAuthenticateInvalidRecaptcha() { - $identifiers = new IdentifierCollection([ 'Authentication.Password' ]); diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 7420ef9ff..0335531c2 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -15,6 +15,7 @@ use Authentication\Authenticator\Result; use Authentication\Controller\Component\AuthenticationComponent; use Authentication\Identity; +use CakeDC\Users\Model\Entity\User; use Cake\Controller\ComponentRegistry; use Cake\Controller\Controller; use Cake\Event\Event; @@ -22,7 +23,6 @@ use Cake\ORM\Entity; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; -use CakeDC\Users\Model\Entity\User; use PHPUnit_Framework_MockObject_RuntimeException; abstract class BaseTraitTest extends TestCase @@ -232,11 +232,10 @@ protected function _mockAuthentication($user = null) 'loginRedirect' => $this->successLoginRedirect, 'logoutRedirect' => $this->logoutRedirect, 'loginAction' => $this->loginAction - ]);; + ]); + ; } - - /** * mock utility * diff --git a/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php b/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php index 0baa0f823..a1ea43118 100644 --- a/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php +++ b/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php @@ -11,16 +11,16 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use Cake\ORM\TableRegistry; use CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Controller\Traits\GoogleVerify; use Cake\Core\Configure; use Cake\Http\ServerRequest; +use Cake\ORM\TableRegistry; class GoogleVerifyTest extends BaseTraitTest { - protected $loginPage = '/login-page'; + protected $loginPage = '/login-page'; /** * setup * diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index a17061118..8008393f0 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -11,11 +11,11 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use Cake\Http\Response; -use Cake\Http\ServerRequestFactory; use Cake\Core\Configure; use Cake\Event\Event; +use Cake\Http\Response; use Cake\Http\ServerRequest; +use Cake\Http\ServerRequestFactory; use Cake\I18n\Time; use Cake\ORM\TableRegistry; use League\OAuth2\Client\Provider\FacebookUser; @@ -116,7 +116,7 @@ public function testLinkSocialHappy() ->getMockForTrait(); $this->Trait->request = ServerRequestFactory::fromGlobals(); - $this->Trait->request->getSession()->write('oauth2state','__TEST_STATE__'); + $this->Trait->request->getSession()->write('oauth2state', '__TEST_STATE__'); $uri = new Uri('/callback-link-social/facebook'); $this->Trait->request = $this->Trait->request->withUri($uri); @@ -124,7 +124,7 @@ public function testLinkSocialHappy() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $this->Trait->request = $this->Trait->request->withAttribute('params',[ + $this->Trait->request = $this->Trait->request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial', @@ -235,7 +235,7 @@ public function testCallbackLinkSocialHappy() ->getMockForTrait(); $this->Trait->request = ServerRequestFactory::fromGlobals(); - $this->Trait->request->getSession()->write('oauth2state','__TEST_STATE__'); + $this->Trait->request->getSession()->write('oauth2state', '__TEST_STATE__'); $uri = new Uri('/callback-link-social/facebook'); $this->Trait->request = $this->Trait->request->withUri($uri); @@ -243,7 +243,7 @@ public function testCallbackLinkSocialHappy() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $this->Trait->request = $this->Trait->request->withAttribute('params',[ + $this->Trait->request = $this->Trait->request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial', @@ -384,7 +384,7 @@ public function testCallbackLinkSocialWithValidationErrors() ->will($this->returnValue($Table)); $this->Trait->request = ServerRequestFactory::fromGlobals(); - $this->Trait->request->getSession()->write('oauth2state','__TEST_STATE__'); + $this->Trait->request->getSession()->write('oauth2state', '__TEST_STATE__'); $uri = new Uri('/callback-link-social/facebook'); $this->Trait->request = $this->Trait->request->withUri($uri); @@ -392,7 +392,7 @@ public function testCallbackLinkSocialWithValidationErrors() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $this->Trait->request = $this->Trait->request->withAttribute('params',[ + $this->Trait->request = $this->Trait->request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial', @@ -443,11 +443,11 @@ public function testCallbackLinkSocialQueryHasErrors() ->getMockForTrait(); $this->Trait->request = ServerRequestFactory::fromGlobals(); - $this->Trait->request->getSession()->write('oauth2state','__TEST_STATE__'); + $this->Trait->request->getSession()->write('oauth2state', '__TEST_STATE__'); $uri = new Uri('/callback-link-social/facebook'); $this->Trait->request = $this->Trait->request->withUri($uri); - $this->Trait->request = $this->Trait->request->withAttribute('params',[ + $this->Trait->request = $this->Trait->request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial', @@ -504,11 +504,11 @@ public function testCallbackLinkSocialUnknownProvider() ->getMockForTrait(); $this->Trait->request = ServerRequestFactory::fromGlobals(); - $this->Trait->request->getSession()->write('oauth2state','__TEST_STATE__'); + $this->Trait->request->getSession()->write('oauth2state', '__TEST_STATE__'); $uri = new Uri('/callback-link-social/facebook'); $this->Trait->request = $this->Trait->request->withUri($uri); - $this->Trait->request = $this->Trait->request->withAttribute('params',[ + $this->Trait->request = $this->Trait->request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial', diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index c5ea44da5..076b70d2e 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -12,10 +12,9 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use CakeDC\Users\Controller\Component\UsersAuthComponent; +use CakeDC\Users\Middleware\SocialAuthMiddleware; use Cake\Event\Event; use Cake\Http\ServerRequest; -use Cake\ORM\Entity; -use CakeDC\Users\Middleware\SocialAuthMiddleware; class LoginTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index 870cda9a0..2e5b1e601 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -11,9 +11,9 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; +use CakeDC\Users\Middleware\SocialAuthMiddleware; use Cake\Http\Response; use Cake\Http\ServerRequest; -use CakeDC\Users\Middleware\SocialAuthMiddleware; class SocialTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index 5dc667c34..f426eda69 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -8,12 +8,12 @@ namespace CakeDC\Users\Test\TestCase\Middleware; +use CakeDC\Users\Middleware\SocialAuthMiddleware; +use CakeDC\Users\Model\Entity\User; use Cake\Core\Configure; use Cake\Http\Response; use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; -use CakeDC\Users\Middleware\SocialAuthMiddleware; -use CakeDC\Users\Model\Entity\User; use League\OAuth2\Client\Provider\FacebookUser; use Zend\Diactoros\Uri; @@ -35,7 +35,6 @@ class SocialAuthMiddlewareTest extends TestCase */ public $Request; - /** * Setup the test case, backup the static object values so they can be restored. * Specifically backs up the contents of Configure and paths in App if they have @@ -111,7 +110,7 @@ public function testProceedStepOne() $uri = new Uri('/auth/facebook'); $this->Request = $this->Request->withUri($uri); - $this->Request = $this->Request->withAttribute('params',[ + $this->Request = $this->Request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', @@ -126,7 +125,6 @@ public function testProceedStepOne() ->method('getAuthorizationUrl') ->will($this->returnValue('http://facebook.com/redirect/url')); - $Middleware = new SocialAuthMiddleware(); $response = new Response(); $next = function () { @@ -161,13 +159,13 @@ public function testSuccessfullyAuthenticated() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $this->Request = $this->Request->withAttribute('params',[ + $this->Request = $this->Request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'provider' => 'facebook' ]); - $this->Request->getSession()->write('oauth2state','__TEST_STATE__'); + $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); $Token = new \League\OAuth2\Client\Token\AccessToken([ 'access_token' => 'test-token', @@ -256,13 +254,13 @@ public function testErrorGetUser() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $this->Request = $this->Request->withAttribute('params',[ + $this->Request = $this->Request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'provider' => 'facebook' ]); - $this->Request->getSession()->write('oauth2state','__TEST_STATE__'); + $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); $Token = new \League\OAuth2\Client\Token\AccessToken([ 'access_token' => 'test-token', diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index f4ebf0eb6..0dc8c753e 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -2,14 +2,14 @@ namespace CakeDC\Users\Test\TestCase\Middleware; +use CakeDC\Users\Middleware\SocialEmailMiddleware; +use CakeDC\Users\Model\Entity\User; +use CakeDC\Users\Social\Mapper\Facebook; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; use Cake\Http\Response; use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; -use CakeDC\Users\Social\Mapper\Facebook; -use CakeDC\Users\Middleware\SocialEmailMiddleware; -use CakeDC\Users\Model\Entity\User; use League\OAuth2\Client\Provider\FacebookUser; use Zend\Diactoros\Uri; @@ -60,7 +60,6 @@ public function setUp() ]; Configure::write('OAuth.providers.facebook', $config); - $this->Request = ServerRequestFactory::fromGlobals(); } @@ -77,10 +76,10 @@ public function tearDown() } /** - * Test when action with get request - * - * @return void - */ + * Test when action with get request + * + * @return void + */ public function testWithGetRquest() { $Token = new \League\OAuth2\Client\Token\AccessToken([ @@ -132,7 +131,7 @@ public function testWithGetRquest() $uri = new Uri('/auth/facebook'); $this->Request = $this->Request->withUri($uri); - $this->Request = $this->Request->withAttribute('params',[ + $this->Request = $this->Request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail', @@ -166,7 +165,7 @@ public function testWithoutUser() 'email' => 'example@example.com' ]); $this->Request = $this->Request->withMethod('POST'); - $this->Request = $this->Request->withAttribute('params',[ + $this->Request = $this->Request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail', @@ -242,7 +241,7 @@ public function testSuccessfullyAuthenticated() 'email' => 'example@example.com' ]); $this->Request = $this->Request->withMethod('POST'); - $this->Request = $this->Request->withAttribute('params',[ + $this->Request = $this->Request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail', @@ -322,7 +321,7 @@ public function testWithoutEmail() $uri = new Uri('/auth/facebook'); $this->Request = $this->Request->withUri($uri); $this->Request = $this->Request->withMethod('POST'); - $this->Request = $this->Request->withAttribute('params',[ + $this->Request = $this->Request->withAttribute('params', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail', @@ -363,5 +362,4 @@ public function testNotValidAction() $this->assertSame($response, $result['response']); $this->assertSame($this->Request, $result['request']); } - } diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 0e01e474a..6f73c2bde 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -11,10 +11,6 @@ use Authorization\AuthorizationService; use Authorization\Middleware\AuthorizationMiddleware; use Authorization\Middleware\RequestAuthorizationMiddleware; -use Cake\Core\Configure; -use Cake\Http\MiddlewareQueue; -use Cake\Http\Response; -use Cake\Http\ServerRequest; use CakeDC\Auth\Middleware\RbacMiddleware; use CakeDC\Users\Authentication\AuthenticationService as CakeDCAuthenticationService; use CakeDC\Users\Authenticator\FormAuthenticator; @@ -23,6 +19,10 @@ use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; use CakeDC\Users\Plugin; +use Cake\Core\Configure; +use Cake\Http\MiddlewareQueue; +use Cake\Http\Response; +use Cake\Http\ServerRequest; use Cake\TestSuite\IntegrationTestCase; /** @@ -206,7 +206,6 @@ public function testMiddlewareNotGoogleAuthenticationAndNotSocial() $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->get(2)); } - /** * testGetAuthenticationService * diff --git a/tests/TestCase/Policy/RbacPolicyTest.php b/tests/TestCase/Policy/RbacPolicyTest.php index c45ef89b3..5ca08b15a 100644 --- a/tests/TestCase/Policy/RbacPolicyTest.php +++ b/tests/TestCase/Policy/RbacPolicyTest.php @@ -3,11 +3,11 @@ namespace CakeDC\Users\Test\TestCase\Policy; use Authentication\Identity; -use Cake\Http\ServerRequestFactory; -use Cake\TestSuite\TestCase; use CakeDC\Auth\Rbac\Rbac; use CakeDC\Users\Model\Entity\User; use CakeDC\Users\Policy\RbacPolicy; +use Cake\Http\ServerRequestFactory; +use Cake\TestSuite\TestCase; class RbacPolicyTest extends TestCase { diff --git a/tests/TestCase/Social/Locator/DatabaseLocatorTest.php b/tests/TestCase/Social/Locator/DatabaseLocatorTest.php index 0aa068480..ce8939b64 100644 --- a/tests/TestCase/Social/Locator/DatabaseLocatorTest.php +++ b/tests/TestCase/Social/Locator/DatabaseLocatorTest.php @@ -2,11 +2,11 @@ namespace CakeDC\Users\Test\TestCase\Social\Locator; -use Cake\Datasource\Exception\RecordNotFoundException; -use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Exception\InvalidSettingsException; -use CakeDC\Users\Social\Mapper\Facebook; use CakeDC\Users\Social\Locator\DatabaseLocator; +use CakeDC\Users\Social\Mapper\Facebook; +use Cake\Datasource\Exception\RecordNotFoundException; +use Cake\TestSuite\TestCase; class DatabaseLocatorTest extends TestCase { @@ -166,6 +166,5 @@ public function testGetOrCreateInvalidUserModel() $this->expectException(InvalidSettingsException::class); $this->Locator->getOrCreate($user); - } } diff --git a/tests/TestCase/Social/ProviderConfigTest.php b/tests/TestCase/Social/ProviderConfigTest.php index 93ad3c74d..b46a65e17 100644 --- a/tests/TestCase/Social/ProviderConfigTest.php +++ b/tests/TestCase/Social/ProviderConfigTest.php @@ -11,12 +11,11 @@ namespace CakeDC\Users\Test\TestCase\Social; -use Cake\Core\Configure; -use Cake\TestSuite\TestCase; use CakeDC\Users\Auth\Exception\InvalidProviderException; use CakeDC\Users\Auth\Exception\InvalidSettingsException; use CakeDC\Users\Social\ProviderConfig; - +use Cake\Core\Configure; +use Cake\TestSuite\TestCase; /** * Users\Social\ProviderConfig Test Case @@ -290,4 +289,4 @@ public function testWithoutProvidersEnabled() $actual = $Config->getConfig('google'); $this->assertEquals($expected, $actual); } -} \ No newline at end of file +} diff --git a/tests/TestCase/Social/Service/OAuth1ServiceTest.php b/tests/TestCase/Social/Service/OAuth1ServiceTest.php index 1bc84c36d..56ba6130e 100644 --- a/tests/TestCase/Social/Service/OAuth1ServiceTest.php +++ b/tests/TestCase/Social/Service/OAuth1ServiceTest.php @@ -9,16 +9,15 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ - namespace CakeDC\Users\Test\TestCase\Social\Service; +use CakeDC\Users\Social\Service\OAuth1Service; +use CakeDC\Users\Social\Service\ServiceInterface; use Cake\Core\Configure; use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; use Cake\Http\Session; use Cake\TestSuite\TestCase; -use CakeDC\Users\Social\Service\OAuth1Service; -use CakeDC\Users\Social\Service\ServiceInterface; use League\OAuth1\Client\Credentials\TemporaryCredentials; use League\OAuth1\Client\Credentials\TokenCredentials; use League\OAuth1\Client\Server\User; @@ -58,7 +57,7 @@ public function setUp() 'linkSocialUri' => '/link-social/twitter', 'callback_uri' => '/callback-link-social/twitter', 'identifier' => '20003030300303', - 'secret' => 'weakpassword','identifier' => 'clientId', + 'secret' => 'weakpassword', 'identifier' => 'clientId', ], ])->setMethods([ 'getTemporaryCredentials', 'getAuthorizationUrl', 'getTokenCredentials', 'getUserDetails' @@ -104,7 +103,6 @@ public function tearDown() */ public function testConstruct() { - $service = new OAuth1Service([ 'className' => 'League\OAuth1\Client\Server\Twitter', 'mapper' => 'CakeDC\Users\Social\Mapper\Twitter', @@ -209,7 +207,6 @@ public function testIsGetUserStepWhenAllEmpty() $result = $this->Service->isGetUserStep($this->Request); $this->assertFalse($result); - } /** @@ -219,7 +216,6 @@ public function testIsGetUserStepWhenAllEmpty() */ public function testIsGetUserStepWhenOauthTokenEmpty() { - $uri = new Uri('/login'); $sessionConfig = (array)Configure::read('Session') + [ @@ -246,7 +242,6 @@ public function testIsGetUserStepWhenOauthTokenEmpty() */ public function testIsGetUserStepWhenOauthVerifierEmpty() { - $uri = new Uri('/login'); $sessionConfig = (array)Configure::read('Session') + [ @@ -273,7 +268,6 @@ public function testIsGetUserStepWhenOauthVerifierEmpty() */ public function testIsGetUserStepWhenOauthKeysNotPresent() { - $uri = new Uri('/login'); $sessionConfig = (array)Configure::read('Session') + [ @@ -285,7 +279,6 @@ public function testIsGetUserStepWhenOauthKeysNotPresent() 'session' => $session, ]); - $result = $this->Service->isGetUserStep($this->Request); $this->assertFalse($result); } diff --git a/tests/TestCase/Social/Service/OAuth2ServiceTest.php b/tests/TestCase/Social/Service/OAuth2ServiceTest.php index 553756d0a..99a70fdd9 100644 --- a/tests/TestCase/Social/Service/OAuth2ServiceTest.php +++ b/tests/TestCase/Social/Service/OAuth2ServiceTest.php @@ -2,14 +2,14 @@ namespace CakeDC\Users\Test\TestCase\Social\Service; +use CakeDC\Users\Social\Service\OAuth2Service; +use CakeDC\Users\Social\Service\ServiceInterface; use Cake\Core\Configure; use Cake\Http\Exception\BadRequestException; use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; use Cake\Http\Session; use Cake\TestSuite\TestCase; -use CakeDC\Users\Social\Service\OAuth2Service; -use CakeDC\Users\Social\Service\ServiceInterface; use League\OAuth2\Client\Provider\FacebookUser; use Zend\Diactoros\Uri; @@ -30,7 +30,6 @@ class OAuth2ServiceTest extends TestCase */ public $Request; - /** * Setup the test case, backup the static object values so they can be restored. * Specifically backs up the contents of Configure and paths in App if they have @@ -98,7 +97,6 @@ public function tearDown() */ public function testConstruct() { - $service = new OAuth2Service([ 'className' => 'League\OAuth2\Client\Provider\Facebook', 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', @@ -172,7 +170,6 @@ public function testIsGetUserStepWhenEmpty() $result = $this->Service->isGetUserStep($this->Request); $this->assertFalse($result); - } /** @@ -195,7 +192,6 @@ public function testIsGetUserStepWhenNotProvided() $result = $this->Service->isGetUserStep($this->Request); $this->assertFalse($result); - } /** @@ -220,7 +216,6 @@ public function testGetAuthorizationUrl() $actual = $this->Request->getSession()->read('oauth2state'); $expected = '_NEW_STATE_'; $this->assertEquals($expected, $actual); - } /** @@ -234,14 +229,13 @@ public function testGetUser() 'code' => 'ZPO9972j3092304230', 'state' => '__TEST_STATE__' ]); - $this->Request->getSession()->write('oauth2state','__TEST_STATE__'); + $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); $Token = new \League\OAuth2\Client\Token\AccessToken([ 'access_token' => 'test-token', 'expires' => 1490988496 ]); - $user = new FacebookUser([ 'id' => '1', 'name' => 'Test User', @@ -346,8 +340,7 @@ public function testGetUserStateNotEqual() 'code' => 'ZPO9972j3092304230', 'state' => '__Unknown_State__' ]); - $this->Request->getSession()->write('oauth2state','__TEST_STATE__'); - + $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); $this->Provider->expects($this->never()) ->method('getAuthorizationUrl'); @@ -375,7 +368,7 @@ public function testGetUserWithoutCode() $this->Request = $this->Request->withQueryParams([ 'state' => '__TEST_STATE__' ]); - $this->Request->getSession()->write('oauth2state','__TEST_STATE__'); + $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); $this->Provider->expects($this->never()) ->method('getAuthorizationUrl'); diff --git a/tests/TestCase/Social/Service/ServiceFactoryTest.php b/tests/TestCase/Social/Service/ServiceFactoryTest.php index 5af9a45d7..0fcc76d79 100644 --- a/tests/TestCase/Social/Service/ServiceFactoryTest.php +++ b/tests/TestCase/Social/Service/ServiceFactoryTest.php @@ -2,13 +2,13 @@ namespace CakeDC\Users\Test\TestCase\Social\Service; +use CakeDC\Users\Social\Service\OAuth1Service; +use CakeDC\Users\Social\Service\OAuth2Service; +use CakeDC\Users\Social\Service\ServiceFactory; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; -use CakeDC\Users\Social\Service\OAuth1Service; -use CakeDC\Users\Social\Service\OAuth2Service; -use CakeDC\Users\Social\Service\ServiceFactory; class ServiceFactoryTest extends TestCase { From dad73403c017e5328c56d14b68af400b85ee68b1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 28 Jul 2018 16:21:41 -0300 Subject: [PATCH 069/685] moved exception classes from Auth/Exception/* to Exception namespace --- src/{Auth => }/Exception/InvalidProviderException.php | 2 +- src/{Auth => }/Exception/InvalidSettingsException.php | 2 +- .../Exception/MissingEventListenerException.php | 2 +- .../Exception/MissingProviderConfigurationException.php | 2 +- src/Social/Locator/DatabaseLocator.php | 2 +- src/Social/ProviderConfig.php | 8 ++++---- .../{Auth => }/Exception/InvalidProviderExceptionTest.php | 4 ++-- .../{Auth => }/Exception/InvalidSettingsExceptionTest.php | 4 ++-- .../Exception/MissingEventListenerExceptionTest.php | 4 ++-- .../MissingProviderConfigurationExceptionTest.php | 4 ++-- tests/TestCase/Social/Locator/DatabaseLocatorTest.php | 2 +- tests/TestCase/Social/ProviderConfigTest.php | 4 ++-- 12 files changed, 20 insertions(+), 20 deletions(-) rename src/{Auth => }/Exception/InvalidProviderException.php (95%) rename src/{Auth => }/Exception/InvalidSettingsException.php (95%) rename src/{Auth => }/Exception/MissingEventListenerException.php (95%) rename src/{Auth => }/Exception/MissingProviderConfigurationException.php (95%) rename tests/TestCase/{Auth => }/Exception/InvalidProviderExceptionTest.php (89%) rename tests/TestCase/{Auth => }/Exception/InvalidSettingsExceptionTest.php (89%) rename tests/TestCase/{Auth => }/Exception/MissingEventListenerExceptionTest.php (89%) rename tests/TestCase/{Auth => }/Exception/MissingProviderConfigurationExceptionTest.php (89%) diff --git a/src/Auth/Exception/InvalidProviderException.php b/src/Exception/InvalidProviderException.php similarity index 95% rename from src/Auth/Exception/InvalidProviderException.php rename to src/Exception/InvalidProviderException.php index d19eee654..84028b813 100644 --- a/src/Auth/Exception/InvalidProviderException.php +++ b/src/Exception/InvalidProviderException.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Exception; +namespace CakeDC\Users\Exception; use Cake\Core\Exception\Exception; diff --git a/src/Auth/Exception/InvalidSettingsException.php b/src/Exception/InvalidSettingsException.php similarity index 95% rename from src/Auth/Exception/InvalidSettingsException.php rename to src/Exception/InvalidSettingsException.php index fcc3e84b2..ca0f5a20f 100644 --- a/src/Auth/Exception/InvalidSettingsException.php +++ b/src/Exception/InvalidSettingsException.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Exception; +namespace CakeDC\Users\Exception; use Cake\Core\Exception\Exception; diff --git a/src/Auth/Exception/MissingEventListenerException.php b/src/Exception/MissingEventListenerException.php similarity index 95% rename from src/Auth/Exception/MissingEventListenerException.php rename to src/Exception/MissingEventListenerException.php index b404b18cb..4cac7474d 100644 --- a/src/Auth/Exception/MissingEventListenerException.php +++ b/src/Exception/MissingEventListenerException.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Exception; +namespace CakeDC\Users\Exception; use Cake\Core\Exception\Exception; diff --git a/src/Auth/Exception/MissingProviderConfigurationException.php b/src/Exception/MissingProviderConfigurationException.php similarity index 95% rename from src/Auth/Exception/MissingProviderConfigurationException.php rename to src/Exception/MissingProviderConfigurationException.php index 77bcbea22..402dc5ff8 100644 --- a/src/Auth/Exception/MissingProviderConfigurationException.php +++ b/src/Exception/MissingProviderConfigurationException.php @@ -9,7 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Auth\Exception; +namespace CakeDC\Users\Exception; use Exception; diff --git a/src/Social/Locator/DatabaseLocator.php b/src/Social/Locator/DatabaseLocator.php index 65bca084e..e543ad723 100644 --- a/src/Social/Locator/DatabaseLocator.php +++ b/src/Social/Locator/DatabaseLocator.php @@ -1,7 +1,7 @@ Date: Sat, 28 Jul 2018 16:24:56 -0300 Subject: [PATCH 070/685] require cakephp/authentication --- composer.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index baf055643..4c231b673 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,8 @@ }, "require": { "cakephp/cakephp": "^3.6", - "cakedc/auth": "^3.0" + "cakedc/auth": "^3.0", + "cakephp/authentication": "^1.0@RC" }, "require-dev": { "phpunit/phpunit": "^5.0", @@ -41,7 +42,6 @@ "robthree/twofactorauth": "^1.6", "satooshi/php-coveralls": "^2.0", "league/oauth1-client": "^1.7", - "cakephp/authentication": "^1.0@RC", "cakephp/authorization": "^1.0@beta", "cakephp/cakephp-codesniffer": "^3.0" }, @@ -53,7 +53,8 @@ "luchianenco/oauth2-amazon": "Provides Social Authentication with Amazon", "league/oauth2-linkedin": "Provides Social Authentication with LinkedIn", "google/recaptcha": "Provides reCAPTCHA validation for registration form", - "robthree/twofactorauth": "Provides Google Authenticator functionality" + "robthree/twofactorauth": "Provides Google Authenticator functionality", + "cakephp/authorization": "Provide authorization for users" }, "autoload": { "psr-4": { From 3fbb22881b6d5e1831237c62cdce2bfc3abbad88 Mon Sep 17 00:00:00 2001 From: Chokri K Date: Thu, 2 Aug 2018 12:21:26 +0100 Subject: [PATCH 071/685] Checking PHPCS Error --- phpunit.xml | 36 ++++++++++++++++++++++++++++++++++ src/View/Helper/UserHelper.php | 9 ++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 phpunit.xml diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 000000000..500c19975 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + ./tests/TestCase + + + + + ./src + + + + + + + + + + + + diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 90f2c8150..ba23e5c0c 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -231,9 +231,12 @@ public function socialConnectLinkList($socialAccounts = []) return ""; } $html = ""; - $connectedProviders = array_map(function ($item) { - return strtolower($item->provider); - }, (array) $socialAccounts); + $connectedProviders = array_map( + function ($item) { + return strtolower($item->provider); + }, + (array)$socialAccounts + ); $providers = Configure::read('OAuth.providers'); foreach ($providers as $name => $provider) { From 855d834c10f26941523c37f7015f3bb97c2c37bf Mon Sep 17 00:00:00 2001 From: Chokri K Date: Thu, 2 Aug 2018 12:22:07 +0100 Subject: [PATCH 072/685] Checking PHPCS Error --- phpunit.xml | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 phpunit.xml diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index 500c19975..000000000 --- a/phpunit.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - ./tests/TestCase - - - - - ./src - - - - - - - - - - - - From 06c32d49a5efbb4a8ec73e4a67eb92fba05eff0b Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 31 Aug 2018 09:26:38 +0200 Subject: [PATCH 073/685] Fix issue with facebook link removed from API #717 --- src/Auth/Social/Mapper/Facebook.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Auth/Social/Mapper/Facebook.php b/src/Auth/Social/Mapper/Facebook.php index b578fe82d..fbefa5010 100644 --- a/src/Auth/Social/Mapper/Facebook.php +++ b/src/Auth/Social/Mapper/Facebook.php @@ -41,4 +41,12 @@ 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') ?: '#'; + } } From fb7112d40f35feffd290ce0867720ed4dc67a877 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Fri, 14 Sep 2018 15:05:57 +0200 Subject: [PATCH 074/685] Add SetupComponent --- src/Controller/Component/SetupComponent.php | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/Controller/Component/SetupComponent.php diff --git a/src/Controller/Component/SetupComponent.php b/src/Controller/Component/SetupComponent.php new file mode 100644 index 000000000..a565dd300 --- /dev/null +++ b/src/Controller/Component/SetupComponent.php @@ -0,0 +1,30 @@ +getController()->loadComponent('CakeDC/Users.UsersAuth'); + $this->getController()->Auth->deny(); + $this->getController()->Auth->allow(['display', 'login']); + } +} \ No newline at end of file From 0a2f736661d5fcbda54d1aa250168d0fca5f977a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 18 Sep 2018 11:18:24 +0100 Subject: [PATCH 075/685] Update Installation.md fix order to prevent issues on setup --- Docs/Documentation/Installation.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 18b244230..bd8a34803 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -46,6 +46,15 @@ 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: @@ -58,15 +67,6 @@ Note you don't need to use the provided tables, you could customize the table na 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 -Load the Plugin ------------ - -Ensure the Users Plugin is loaded in your config/bootstrap.php file - -``` -Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); -``` - Customization ---------- From 788e7630c82ebe8b1a20d778070d2d3dbb76489f Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 9 Oct 2018 13:43:19 +0200 Subject: [PATCH 076/685] Update setup component --- src/Controller/Component/SetupComponent.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Controller/Component/SetupComponent.php b/src/Controller/Component/SetupComponent.php index a565dd300..291935a16 100644 --- a/src/Controller/Component/SetupComponent.php +++ b/src/Controller/Component/SetupComponent.php @@ -13,6 +13,7 @@ use Cake\Controller\Component; +use Cake\Core\Configure; class SetupComponent extends Component { @@ -23,8 +24,12 @@ class SetupComponent extends Component public function initialize(array $config) { parent::initialize($config); - $this->getController()->loadComponent('CakeDC/Users.UsersAuth'); - $this->getController()->Auth->deny(); - $this->getController()->Auth->allow(['display', 'login']); + 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']); + } } } \ No newline at end of file From a1bf8ca020621ab8de9b701af2eb3a88a0158eaf Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Tue, 9 Oct 2018 13:50:45 +0200 Subject: [PATCH 077/685] Add users auth component load to setup --- src/Controller/Component/SetupComponent.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Controller/Component/SetupComponent.php b/src/Controller/Component/SetupComponent.php index 291935a16..1821417c1 100644 --- a/src/Controller/Component/SetupComponent.php +++ b/src/Controller/Component/SetupComponent.php @@ -24,6 +24,7 @@ class SetupComponent extends Component public function initialize(array $config) { parent::initialize($config); + $this->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 From d8ad1a89ba06c9ceca30faf4e35ae798ee0e8476 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 18 Oct 2018 10:09:42 -0300 Subject: [PATCH 078/685] Using CakeRouteUrlChecker for authentication --- config/users.php | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/config/users.php b/config/users.php index ffda7efda..600f62ee8 100644 --- a/config/users.php +++ b/config/users.php @@ -127,8 +127,18 @@ ], 'Auth' => [ 'AuthenticationComponent' => [ - 'loginAction' => '/login', - 'logoutRedirect' => '/login', + 'loginAction' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + 'prefix' => false, + ], + 'logoutRedirect' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + 'prefix' => false, + ], 'loginRedirect' => '/', 'requireIdentity' => false ], @@ -138,7 +148,13 @@ 'sessionKey' => 'Auth', ], 'CakeDC/Users.Form' => [ - 'loginUrl' => '/login' + 'urlChecker' => 'Authentication.CakeRouter', + 'loginUrl' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + 'prefix' => false, + ] ], 'Authentication.Token' => [ 'skipGoogleVerify' => true, @@ -153,7 +169,13 @@ 'expires' => '1 month', 'httpOnly' => true, ], - 'loginUrl' => '/login' + 'urlChecker' => 'Authentication.CakeRouter', + 'loginUrl' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + 'prefix' => false, + ] ], ], 'Identifiers' => [ From 7971f5d6369bd506bfc51ee53148235baa4a1b3a Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 18 Oct 2018 10:13:27 -0300 Subject: [PATCH 079/685] Using CakeRouteUrlChecker for authentication --- config/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index 600f62ee8..569c71bc8 100644 --- a/config/users.php +++ b/config/users.php @@ -136,7 +136,7 @@ 'logoutRedirect' => [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', - 'action' => 'login', + 'action' => 'logout', 'prefix' => false, ], 'loginRedirect' => '/', From 85f50e9ae5621d85a116d0a43ba011d7e06e661f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 18 Oct 2018 10:26:21 -0300 Subject: [PATCH 080/685] Trigger error if app has config Auth.authenticate or Auth.authorize --- config/bootstrap.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index e0bbb3cae..ee514ef5e 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -21,10 +21,9 @@ 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::check('Auth.authenticate') || Configure::check('Auth.authorize')) { + trigger_error("Users plugin configurations keys Auth.authenticate and Auth.authorize was removed, please check what have changed at migration guide https://github.com/CakeDC/users/blob/master/Docs/Documentation/MigrationGuide.md'"); } - $oauthPath = Configure::read('OAuth.path'); if (is_array($oauthPath)) { Router::scope('/auth', function ($routes) use ($oauthPath) { From 39b3b1f6b5932919a5274c019a7c62c63fec6a01 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 18 Oct 2018 10:37:11 -0300 Subject: [PATCH 081/685] using constant for google verify session key --- src/Authentication/AuthenticationService.php | 3 ++- src/Controller/Traits/GoogleVerifyTrait.php | 11 ++++++----- src/Controller/Traits/LoginTrait.php | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Authentication/AuthenticationService.php b/src/Authentication/AuthenticationService.php index 2b49d15de..72f29555c 100644 --- a/src/Authentication/AuthenticationService.php +++ b/src/Authentication/AuthenticationService.php @@ -15,6 +15,7 @@ class AuthenticationService extends BaseService { const NEED_GOOGLE_VERIFY = 'NEED_GOOGLE_VERIFY'; + const GOOGLE_VERIFY_SESSION_KEY = 'temporarySession'; /** * Proceed to google verify action after a valid result result * @@ -25,7 +26,7 @@ class AuthenticationService extends BaseService */ protected function proceedToGoogleVerify(ServerRequestInterface $request, ResponseInterface $response, ResultInterface $result) { - $request->getSession()->write('temporarySession', $result->getData()); + $request->getSession()->write(self::GOOGLE_VERIFY_SESSION_KEY, $result->getData()); $result = new Result(null, self::NEED_GOOGLE_VERIFY); diff --git a/src/Controller/Traits/GoogleVerifyTrait.php b/src/Controller/Traits/GoogleVerifyTrait.php index ac1a5d9fa..079ef49a3 100644 --- a/src/Controller/Traits/GoogleVerifyTrait.php +++ b/src/Controller/Traits/GoogleVerifyTrait.php @@ -3,6 +3,7 @@ namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; +use CakeDC\Users\Authentication\AuthenticationService; trait GoogleVerifyTrait { @@ -22,7 +23,7 @@ public function verify() return $this->redirect($loginAction); } - $temporarySession = $this->request->getSession()->read('temporarySession'); + $temporarySession = $this->request->getSession()->read(AuthenticationService::GOOGLE_VERIFY_SESSION_KEY); $secretVerified = $temporarySession['secret_verified']; // showing QR-code until shared secret is verified if (!$secretVerified) { @@ -58,7 +59,7 @@ protected function isVerifyAllowed() return true; } - $temporarySession = $this->request->getSession()->read('temporarySession'); + $temporarySession = $this->request->getSession()->read(AuthenticationService::GOOGLE_VERIFY_SESSION_KEY); if (empty($temporarySession)) { $message = __d('CakeDC/Users', 'Could not find user data'); @@ -93,7 +94,7 @@ protected function onVerifyGetSecret($user) ->where(['id' => $user['id']]); $query->execute(); $user['secret'] = $secret; - $this->request->getSession()->write('temporarySession', $user); + $this->request->getSession()->write(AuthenticationService::GOOGLE_VERIFY_SESSION_KEY, $user); } catch (\Exception $e) { $this->request->getSession()->destroy(); $message = $e->getMessage(); @@ -116,7 +117,7 @@ protected function onPostVerifyCode($loginAction) { $codeVerified = false; $verificationCode = $this->request->getData('code'); - $user = $this->request->getSession()->read('temporarySession'); + $user = $this->request->getSession()->read(AuthenticationService::GOOGLE_VERIFY_SESSION_KEY); $entity = $this->getUsersTable()->get($user['id']); if (!empty($entity['secret'])) { @@ -153,7 +154,7 @@ protected function onPostVerifyCodeOkay($loginAction, $user) ->execute(); } - $this->request->getSession()->delete('temporarySession'); + $this->request->getSession()->delete(AuthenticationService::GOOGLE_VERIFY_SESSION_KEY); $this->request->getSession()->write('GoogleTwoFactor.User', $user); return $this->redirect($loginAction); diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 987f3c14c..1bf0ecdc6 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -11,10 +11,10 @@ namespace CakeDC\Users\Controller\Traits; -use Authentication\AuthenticationService; use Authentication\Authenticator\Result; use CakeDC\Users\Authenticator\AuthenticatorFeedbackInterface; use CakeDC\Users\Authenticator\FormAuthenticator; +use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Plugin; use Cake\Core\Configure; @@ -106,7 +106,7 @@ public function socialLogin() */ public function login() { - $this->request->getSession()->delete('temporarySession'); + $this->request->getSession()->delete(AuthenticationService::GOOGLE_VERIFY_SESSION_KEY); $result = $this->request->getAttribute('authentication')->getResult(); if ($result->isValid()) { From ac81892a78a3a3d117302f1016c68854016c4aad Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 18 Oct 2018 10:47:52 -0300 Subject: [PATCH 082/685] Added constant for socialRawData attribute name assigned by Social auth middleware --- src/Controller/Traits/LoginTrait.php | 2 +- src/Middleware/SocialAuthMiddleware.php | 5 ++++- tests/TestCase/Middleware/SocialAuthMiddlewareTest.php | 6 +++--- tests/TestCase/Middleware/SocialEmailMiddlewareTest.php | 3 ++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 1bf0ecdc6..88ee20ae5 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -94,7 +94,7 @@ public function socialLogin() throw new NotFoundException(); } - $data = $this->request->getAttribute('socialRawData'); + $data = $this->request->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA); return $this->failedSocialLogin($status, $data); } diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 3170895c7..ab96065b7 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -29,6 +29,9 @@ class SocialAuthMiddleware const AUTH_ERROR_FIND_USER = 50; const AUTH_SUCCESS = 100; + const ATTRIBUTE_NAME_SOCIAL_RAW_DATA = 'socialRawData'; + const ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS = 'socialAuthStatus'; + protected $_defaultConfig = []; protected $authStatus = 0; protected $rawData = []; @@ -86,7 +89,7 @@ protected function finishWithResult($result, ServerRequest $request, ResponseInt } $request = $request->withAttribute('socialAuthStatus', $this->authStatus); - $request = $request->withAttribute('socialRawData', $this->rawData); + $request = $request->withAttribute(self::ATTRIBUTE_NAME_SOCIAL_RAW_DATA, $this->rawData); return $next($request, $response); } diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index f426eda69..10c12e608 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -235,8 +235,8 @@ public function testSuccessfullyAuthenticated() $result = $Middleware($this->Request, $response, $next); $this->assertEquals(SocialAuthMiddleware::AUTH_SUCCESS, $result['request']->getAttribute('socialAuthStatus')); - $this->assertNotEmpty($result['request']->getAttribute('socialRawData')); - $this->assertNotEmpty($result['request']->getAttribute('socialRawData')['id']); + $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); + $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)['id']); $this->assertInstanceOf(User::class, $this->Request->getSession()->read('Auth')); $this->assertEquals(200, $result['response']->getStatusCode()); } @@ -294,7 +294,7 @@ public function testErrorGetUser() $result = $Middleware($this->Request, $response, $next); $this->assertEquals(0, $result['request']->getAttribute('socialAuthStatus')); - $this->assertEmpty($result['request']->getAttribute('socialRawData')); + $this->assertEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); $this->assertEmpty($this->Request->getSession()->read('Auth')); $this->assertEquals(200, $result['response']->getStatusCode()); } diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index 0dc8c753e..d6dcc7fdc 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -2,6 +2,7 @@ namespace CakeDC\Users\Test\TestCase\Middleware; +use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; use CakeDC\Users\Model\Entity\User; use CakeDC\Users\Social\Mapper\Facebook; @@ -147,7 +148,7 @@ public function testWithGetRquest() $this->assertTrue(is_array($result)); $this->assertEquals(null, $result['request']->getAttribute('socialAuthStatus')); - $this->assertEmpty($result['request']->getAttribute('socialRawData')); + $this->assertEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); $this->assertEmpty($this->Request->getSession()->read('Auth')); $this->assertEmpty($this->Request->getSession()->read('Users.successSocialLogin')); } From bab1f6a289812fa1a7aa99c6b506286b1544e500 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 18 Oct 2018 10:49:09 -0300 Subject: [PATCH 083/685] Added constant for socialRawData attribute name assigned by Social auth middleware --- tests/TestCase/Middleware/SocialEmailMiddlewareTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index d6dcc7fdc..f2d581b76 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -259,8 +259,8 @@ public function testSuccessfullyAuthenticated() $this->assertEquals(200, $result['response']->getStatusCode()); $this->assertEquals(SocialEmailMiddleware::AUTH_SUCCESS, $result['request']->getAttribute('socialAuthStatus')); - $this->assertNotEmpty($result['request']->getAttribute('socialRawData')); - $this->assertNotEmpty($result['request']->getAttribute('socialRawData')['id']); + $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); + $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)['id']); $this->assertInstanceOf(User::class, $this->Request->getSession()->read('Auth')); $this->assertTrue($this->Request->getSession()->read('Users.successSocialLogin')); } @@ -339,7 +339,7 @@ public function testWithoutEmail() $this->assertEquals(200, $result['response']->getStatusCode()); $this->assertEquals(0, $result['request']->getAttribute('socialAuthStatus')); - $this->assertEmpty($result['request']->getAttribute('socialRawData')); + $this->assertEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); $this->assertEmpty($this->Request->getSession()->read('Auth')); } From 23c8a37a04b845ebe96b3241a5dd496a7c5a9a57 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 18 Oct 2018 11:01:10 -0300 Subject: [PATCH 084/685] Added constant for socialAuthStatus attribute name assigned by Social auth middleware --- src/Controller/Traits/LoginTrait.php | 2 +- src/Controller/Traits/SocialTrait.php | 2 +- src/Middleware/SocialAuthMiddleware.php | 2 +- tests/TestCase/Controller/Traits/SocialTraitTest.php | 2 +- tests/TestCase/Middleware/SocialAuthMiddlewareTest.php | 4 ++-- tests/TestCase/Middleware/SocialEmailMiddlewareTest.php | 6 +++--- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 88ee20ae5..8f634965d 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -82,7 +82,7 @@ public function failedSocialLogin($error, $data, $flash = false) */ public function socialLogin() { - $status = $this->request->getAttribute('socialAuthStatus'); + $status = $this->request->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS); if ($status === SocialAuthMiddleware::AUTH_SUCCESS) { $user = $this->request->getAttribute('identity')->getOriginalData(); diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 7ca44427b..147381de4 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -30,7 +30,7 @@ trait SocialTrait public function socialEmail() { if ($this->request->is('post')) { - $status = $this->request->getAttribute('socialAuthStatus'); + $status = $this->request->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS); if ($status === SocialAuthMiddleware::AUTH_ERROR_INVALID_RECAPTCHA) { $this->Flash->error(__d('CakeDC/Users', 'The reCaptcha could not be validated')); diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index ab96065b7..21a82cb89 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -88,7 +88,7 @@ protected function finishWithResult($result, ServerRequest $request, ResponseInt $request->getSession()->write('Users.successSocialLogin', true); } - $request = $request->withAttribute('socialAuthStatus', $this->authStatus); + $request = $request->withAttribute(self::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS, $this->authStatus); $request = $request->withAttribute(self::ATTRIBUTE_NAME_SOCIAL_RAW_DATA, $this->rawData); return $next($request, $response); diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index 2e5b1e601..0d2fab13b 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -120,7 +120,7 @@ public function testSocialEmailInvalidRecaptcha() ->with('post') ->will($this->returnValue(true)); $this->_mockAuthentication(); - $this->Trait->request = $this->Trait->request->withAttribute('socialAuthStatus', SocialAuthMiddleware::AUTH_ERROR_INVALID_RECAPTCHA); + $this->Trait->request = $this->Trait->request->withAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS, SocialAuthMiddleware::AUTH_ERROR_INVALID_RECAPTCHA); $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') ->setMethods(['error']) ->disableOriginalConstructor() diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index 10c12e608..cf44a2309 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -234,7 +234,7 @@ public function testSuccessfullyAuthenticated() }; $result = $Middleware($this->Request, $response, $next); - $this->assertEquals(SocialAuthMiddleware::AUTH_SUCCESS, $result['request']->getAttribute('socialAuthStatus')); + $this->assertEquals(SocialAuthMiddleware::AUTH_SUCCESS, $result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS)); $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)['id']); $this->assertInstanceOf(User::class, $this->Request->getSession()->read('Auth')); @@ -293,7 +293,7 @@ public function testErrorGetUser() }; $result = $Middleware($this->Request, $response, $next); - $this->assertEquals(0, $result['request']->getAttribute('socialAuthStatus')); + $this->assertEquals(0, $result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS)); $this->assertEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); $this->assertEmpty($this->Request->getSession()->read('Auth')); $this->assertEquals(200, $result['response']->getStatusCode()); diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index f2d581b76..6671afb01 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -147,7 +147,7 @@ public function testWithGetRquest() $result = $Middleware($this->Request, $response, $next); $this->assertTrue(is_array($result)); - $this->assertEquals(null, $result['request']->getAttribute('socialAuthStatus')); + $this->assertEquals(null, $result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS)); $this->assertEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); $this->assertEmpty($this->Request->getSession()->read('Auth')); $this->assertEmpty($this->Request->getSession()->read('Users.successSocialLogin')); @@ -258,7 +258,7 @@ public function testSuccessfullyAuthenticated() $this->assertTrue(is_array($result)); $this->assertEquals(200, $result['response']->getStatusCode()); - $this->assertEquals(SocialEmailMiddleware::AUTH_SUCCESS, $result['request']->getAttribute('socialAuthStatus')); + $this->assertEquals(SocialEmailMiddleware::AUTH_SUCCESS, $result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS)); $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)['id']); $this->assertInstanceOf(User::class, $this->Request->getSession()->read('Auth')); @@ -338,7 +338,7 @@ public function testWithoutEmail() $this->assertTrue(is_array($result)); $this->assertEquals(200, $result['response']->getStatusCode()); - $this->assertEquals(0, $result['request']->getAttribute('socialAuthStatus')); + $this->assertEquals(0, $result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS)); $this->assertEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); $this->assertEmpty($this->Request->getSession()->read('Auth')); } From 6bbf0f6b570e38255a574bf834ddc684751f3efd Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 14:39:56 -0300 Subject: [PATCH 085/685] Social auth location config updated, rename finder option to authFinder --- config/users.php | 2 +- src/Social/Locator/DatabaseLocator.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/users.php b/config/users.php index 569c71bc8..c9ce8510c 100644 --- a/config/users.php +++ b/config/users.php @@ -211,7 +211,7 @@ 'sessionAuthKey' => 'Auth', 'locator' => [ 'usernameField' => 'username', - 'finder' => 'all', + 'authFinder' => 'all', ] ], 'OAuth' => [ diff --git a/src/Social/Locator/DatabaseLocator.php b/src/Social/Locator/DatabaseLocator.php index e543ad723..b4b4a3843 100644 --- a/src/Social/Locator/DatabaseLocator.php +++ b/src/Social/Locator/DatabaseLocator.php @@ -21,7 +21,7 @@ class DatabaseLocator implements LocatorInterface const ERROR_INVALID_RECAPTCHA = 40; protected $_defaultConfig = [ - 'finder' => 'all', + 'authFinder' => 'all', ]; /** @@ -73,7 +73,7 @@ protected function findUser($user) { $userModel = $this->getConfig('userModel'); $table = TableRegistry::getTableLocator()->get($userModel); - $finder = $this->getConfig('finder'); + $finder = $this->getConfig('authFinder'); $primaryKey = (array)$table->getPrimaryKey(); From 82d0cef10f0d358c175603c4971dbd33cd7dd213 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 15:02:16 -0300 Subject: [PATCH 086/685] DI for FormAuthentication base class --- src/Authenticator/FormAuthenticator.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Authenticator/FormAuthenticator.php b/src/Authenticator/FormAuthenticator.php index bd23074f7..b1f979221 100644 --- a/src/Authenticator/FormAuthenticator.php +++ b/src/Authenticator/FormAuthenticator.php @@ -76,11 +76,21 @@ protected function getBaseAuthenticator() * @param \Authentication\Identifier\IdentifierInterface $identifier Identifier or identifiers collection. * @param array $config Configuration settings. * - * @return \Authentication\Authenticator\FormAuthenticator + * @return \Authentication\Authenticator\AuthenticatorInterface */ protected function createBaseAuthenticator(IdentifierInterface $identifier, array $config = []) { - return new BaseFormAuthenticator($identifier, $config); + if (!isset($config['baseClassName'])) { + return new BaseFormAuthenticator($identifier, $config); + } + + $className = $config['baseClassName']; + unset($config['baseClassName']); + if (!class_exists($className)) { + throw new \InvalidArgumentException(__("Base class for FormAuthenticator {0} does not exists", $className)); + } + + return new $className($identifier, $config); } /** From ebb569e7851515d398666708c3ca8934d3ff6f25 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 15:17:47 -0300 Subject: [PATCH 087/685] We should load auth components at users controller not app controller. Permission is already set by permisssions.php --- src/Controller/AppController.php | 33 ------------------------------ src/Controller/UsersController.php | 32 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index f72d6b530..c7457a2f3 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -12,7 +12,6 @@ namespace CakeDC\Users\Controller; use App\Controller\AppController as BaseController; -use Cake\Core\Configure; /** * AppController for Users Plugin @@ -20,27 +19,6 @@ */ class AppController extends BaseController { - protected $_defaultAuthorizationConfig = [ - 'skipAuthorization' => [ - 'validateAccount', - // LoginTrait - 'socialLogin', - 'login', - 'logout', - 'socialEmail', - 'verify', - // RegisterTrait - 'register', - 'validateEmail', - // PasswordManagementTrait used in RegisterTrait - 'changePassword', - 'resetPassword', - 'requestResetPassword', - // UserValidationTrait used in PasswordManagementTrait - 'resendTokenValidation', - ] - ]; - /** * Initialize * @@ -53,16 +31,5 @@ public function initialize() if ($this->request->getParam('_csrfToken') === false) { $this->loadComponent('Csrf'); } - $this->loadComponent('Authentication.Authentication', Configure::read('Auth.AuthenticationComponent')); - - if (Configure::read('Auth.AuthorizationComponent.enable') !== false) { - $config = (array)Configure::read('Auth.AuthorizationComponent') + $this->_defaultAuthorizationConfig; - - $this->loadComponent('Authorization.Authorization', $config); - } - - if (Configure::read('Users.GoogleAuthenticator.login') !== false) { - $this->loadComponent('CakeDC/Users.GoogleAuthenticator'); - } } } diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index f1ea5deb0..bc4c97262 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller; +use Cake\Core\Configure; use CakeDC\Users\Controller\Traits\GoogleVerifyTrait; use CakeDC\Users\Controller\Traits\LinkSocialTrait; use CakeDC\Users\Controller\Traits\LoginTrait; @@ -36,4 +37,35 @@ class UsersController extends AppController use RegisterTrait; use SimpleCrudTrait; use SocialTrait; + + /** + * Initialize + * + * @return void + */ + public function initialize() + { + parent::initialize(); + + $this->loadAuthComponents(); + } + + /** + * Load all auth components needed: Authentication.Authentication, Authorization.Authorization and CakeDC/Users.GoogleAuthenticator + * + * @return void + */ + protected function loadAuthComponents() + { + $this->loadComponent('Authentication.Authentication', Configure::read('Auth.AuthenticationComponent')); + + if (Configure::read('Auth.AuthorizationComponent.enable') !== false) { + $config = (array)Configure::read('Auth.AuthorizationComponent'); + $this->loadComponent('Authorization.Authorization', $config); + } + + if (Configure::read('Users.GoogleAuthenticator.login') !== false) { + $this->loadComponent('CakeDC/Users.GoogleAuthenticator'); + } + } } From 81792b09cbd3055a9c1a947f7cfc77e7d38959ed Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 15:28:26 -0300 Subject: [PATCH 088/685] DI for FormAuthentication base class --- src/Controller/Traits/GoogleVerifyTrait.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/GoogleVerifyTrait.php b/src/Controller/Traits/GoogleVerifyTrait.php index 079ef49a3..42440e291 100644 --- a/src/Controller/Traits/GoogleVerifyTrait.php +++ b/src/Controller/Traits/GoogleVerifyTrait.php @@ -97,8 +97,8 @@ protected function onVerifyGetSecret($user) $this->request->getSession()->write(AuthenticationService::GOOGLE_VERIFY_SESSION_KEY, $user); } catch (\Exception $e) { $this->request->getSession()->destroy(); - $message = $e->getMessage(); - $this->Flash->error($message, 'default', [], 'auth'); + $this->log($e); + $this->Flash->error(__('Could not verify, please try again'), 'default', [], 'auth'); return ''; } From 7a21a3fc2eda5ce2ea4e959e48cf328cd6d1ab8a Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 15:39:40 -0300 Subject: [PATCH 089/685] Checking if user temp data for google verify has id --- src/Controller/Traits/GoogleVerifyTrait.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Controller/Traits/GoogleVerifyTrait.php b/src/Controller/Traits/GoogleVerifyTrait.php index 42440e291..fa8f4342c 100644 --- a/src/Controller/Traits/GoogleVerifyTrait.php +++ b/src/Controller/Traits/GoogleVerifyTrait.php @@ -19,7 +19,7 @@ trait GoogleVerifyTrait public function verify() { $loginAction = Configure::read('Auth.AuthenticationComponent.loginAction'); - if ($this->isVerifyAllowed()) { + if (!$this->isVerifyAllowed()) { return $this->redirect($loginAction); } @@ -56,19 +56,19 @@ protected function isVerifyAllowed() $message = __d('CakeDC/Users', 'Please enable Google Authenticator first.'); $this->Flash->error($message, 'default', [], 'auth'); - return true; + return false; } $temporarySession = $this->request->getSession()->read(AuthenticationService::GOOGLE_VERIFY_SESSION_KEY); - if (empty($temporarySession)) { + if (empty($temporarySession) || !isset($temporarySession['id'])) { $message = __d('CakeDC/Users', 'Could not find user data'); $this->Flash->error($message, 'default', [], 'auth'); - return true; + return false; } - return false; + return true; } /** From c8cc7c7309b383260f0e94c6c1d25f85fdfc614b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 15:51:33 -0300 Subject: [PATCH 090/685] Checking if provider class exists --- src/Authenticator/FormAuthenticator.php | 2 +- src/Middleware/SocialAuthMiddleware.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Authenticator/FormAuthenticator.php b/src/Authenticator/FormAuthenticator.php index b1f979221..91e0b8434 100644 --- a/src/Authenticator/FormAuthenticator.php +++ b/src/Authenticator/FormAuthenticator.php @@ -87,7 +87,7 @@ protected function createBaseAuthenticator(IdentifierInterface $identifier, arra $className = $config['baseClassName']; unset($config['baseClassName']); if (!class_exists($className)) { - throw new \InvalidArgumentException(__("Base class for FormAuthenticator {0} does not exists", $className)); + throw new \InvalidArgumentException(__("Base class for FormAuthenticator {0} does not exist", $className)); } return new $className($identifier, $config); diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 21a82cb89..a10ec29ba 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -179,6 +179,9 @@ protected function _touch(array $data) protected function _mapUser($data) { $providerMapperClass = $this->service->getConfig('mapper'); + if (!class_exists($providerMapperClass)) { + throw new \InvalidArgumentException(__("Provider mapper class {0} does not exist", $providerMapperClass)); + } $providerMapper = new $providerMapperClass($data); $user = $providerMapper(); $user['provider'] = $this->service->getProviderName(); From 690455ba477b58e2611e8f39b8fe5ff75cfabf6c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 16:18:42 -0300 Subject: [PATCH 091/685] Social data mappers don't have $rawData property they expect an argument for invoke method --- tests/TestCase/Social/Mapper/FacebookTest.php | 4 ++-- tests/TestCase/Social/Mapper/GoogleTest.php | 4 ++-- tests/TestCase/Social/Mapper/InstagramTest.php | 4 ++-- tests/TestCase/Social/Mapper/LinkedInTest.php | 4 ++-- tests/TestCase/Social/Mapper/TwitterTest.php | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/TestCase/Social/Mapper/FacebookTest.php b/tests/TestCase/Social/Mapper/FacebookTest.php index 353beef21..78c595173 100644 --- a/tests/TestCase/Social/Mapper/FacebookTest.php +++ b/tests/TestCase/Social/Mapper/FacebookTest.php @@ -65,8 +65,8 @@ public function testMap() 'is_silhouette' => false, 'cover_photo_url' => 'https://scontent.xx.fbcdn.net/v/test.jpg' ]; - $providerMapper = new Facebook($rawData); - $user = $providerMapper(); + $providerMapper = new Facebook(); + $user = $providerMapper($rawData); $this->assertEquals([ 'id' => '1', 'username' => null, diff --git a/tests/TestCase/Social/Mapper/GoogleTest.php b/tests/TestCase/Social/Mapper/GoogleTest.php index 4214a0d5d..67a1c761c 100644 --- a/tests/TestCase/Social/Mapper/GoogleTest.php +++ b/tests/TestCase/Social/Mapper/GoogleTest.php @@ -47,8 +47,8 @@ public function testMap() 'url' => 'https://lh3.googleusercontent.com/photo.jpg' ] ]; - $providerMapper = new Google($rawData); - $user = $providerMapper(); + $providerMapper = new Google(); + $user = $providerMapper($rawData); $this->assertEquals([ 'id' => '1', 'username' => null, diff --git a/tests/TestCase/Social/Mapper/InstagramTest.php b/tests/TestCase/Social/Mapper/InstagramTest.php index 616201ede..9ae7b7d53 100644 --- a/tests/TestCase/Social/Mapper/InstagramTest.php +++ b/tests/TestCase/Social/Mapper/InstagramTest.php @@ -46,8 +46,8 @@ public function testMap() ], 'bio' => '' ]; - $providerMapper = new Instagram($rawData); - $user = $providerMapper(); + $providerMapper = new Instagram(); + $user = $providerMapper($rawData); $this->assertEquals([ 'id' => '1', 'username' => 'test', diff --git a/tests/TestCase/Social/Mapper/LinkedInTest.php b/tests/TestCase/Social/Mapper/LinkedInTest.php index 1273c8356..29a14c3fa 100644 --- a/tests/TestCase/Social/Mapper/LinkedInTest.php +++ b/tests/TestCase/Social/Mapper/LinkedInTest.php @@ -49,8 +49,8 @@ public function testMap() 'pictureUrl' => 'https://media.licdn.com/mpr/mprx/test.jpg', 'publicProfileUrl' => 'https://www.linkedin.com/in/test' ]; - $providerMapper = new LinkedIn($rawData); - $user = $providerMapper(); + $providerMapper = new LinkedIn(); + $user = $providerMapper($rawData); $this->assertEquals([ 'id' => '1', 'username' => null, diff --git a/tests/TestCase/Social/Mapper/TwitterTest.php b/tests/TestCase/Social/Mapper/TwitterTest.php index db75b721d..02ab53b1c 100644 --- a/tests/TestCase/Social/Mapper/TwitterTest.php +++ b/tests/TestCase/Social/Mapper/TwitterTest.php @@ -45,8 +45,8 @@ public function testMap() 'tokenSecret' => 'test-secret' ] ]; - $providerMapper = new Twitter($rawData); - $user = $providerMapper(); + $providerMapper = new Twitter(); + $user = $providerMapper($rawData); $this->assertEquals([ 'id' => '1', 'username' => 'test', From dd8ad4d0faee9ca316f0a12db84b66e3584963c2 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 16:19:22 -0300 Subject: [PATCH 092/685] Social data mappers don't have $rawData property they expect an argument for invoke method --- src/Social/Mapper/AbstractMapper.php | 28 +++++++++++++++------------- src/Social/Mapper/Amazon.php | 11 ++++++++--- src/Social/Mapper/Facebook.php | 7 +++++-- src/Social/Mapper/Google.php | 8 ++++++-- src/Social/Mapper/Instagram.php | 8 ++++++-- src/Social/Mapper/Twitter.php | 16 ++++++++++++---- 6 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/Social/Mapper/AbstractMapper.php b/src/Social/Mapper/AbstractMapper.php index a6aa3e791..767d83c20 100644 --- a/src/Social/Mapper/AbstractMapper.php +++ b/src/Social/Mapper/AbstractMapper.php @@ -53,12 +53,10 @@ abstract class AbstractMapper /** * Constructor * - * @param mixed $rawData raw data * @param mixed $mapFields map fields */ - public function __construct($rawData, $mapFields = null) + public function __construct($mapFields = null) { - $this->_rawData = $rawData; if (!is_null($mapFields)) { $this->_mapFields = $mapFields; } @@ -67,21 +65,24 @@ public function __construct($rawData, $mapFields = null) /** * Invoke method * + * @param mixed $rawData raw data * @return mixed */ - public function __invoke() + public function __invoke($rawData) { - return $this->_map(); + return $this->_map($rawData); } /** * If email is present the user is validated * + * @param mixed $rawData raw data + * * @return bool */ - protected function _validated() + protected function _validated($rawData) { - $email = Hash::get($this->_rawData, $this->_mapFields['email']); + $email = Hash::get($rawData, $this->_mapFields['email']); return !empty($email); } @@ -89,26 +90,27 @@ protected function _validated() /** * Maps raw data using mapFields * + * @param mixed $rawData raw data * @return mixed */ - protected function _map() + protected function _map($rawData) { $result = []; - collection($this->_mapFields)->each(function ($mappedField, $field) use (&$result) { - $value = Hash::get($this->_rawData, $mappedField); + collection($this->_mapFields)->each(function ($mappedField, $field) use (&$result, $rawData) { + $value = Hash::get($rawData, $mappedField); $function = '_' . $field; if (method_exists($this, $function)) { - $value = $this->{$function}(); + $value = $this->{$function}($rawData); } $result[$field] = $value; }); - $token = Hash::get($this->_rawData, 'token'); + $token = Hash::get($rawData, 'token'); $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; + $result['raw'] = $rawData; return $result; } diff --git a/src/Social/Mapper/Amazon.php b/src/Social/Mapper/Amazon.php index 1ca0709f0..34b48ec65 100644 --- a/src/Social/Mapper/Amazon.php +++ b/src/Social/Mapper/Amazon.php @@ -27,17 +27,22 @@ class Amazon extends AbstractMapper /** * Map for provider fields - * @var + * + * @var array */ protected $_mapFields = [ 'id' => 'user_id' ]; /** + * Get link property value + * + * @param mixed $rawData raw data + * * @return string */ - protected function _link() + protected function _link($rawData) { - return self::AMAZON_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['id']); + return self::AMAZON_BASE_URL . Hash::get($rawData, $this->_mapFields['id']); } } diff --git a/src/Social/Mapper/Facebook.php b/src/Social/Mapper/Facebook.php index 55951d666..974c83141 100644 --- a/src/Social/Mapper/Facebook.php +++ b/src/Social/Mapper/Facebook.php @@ -35,10 +35,13 @@ class Facebook extends AbstractMapper /** * Get avatar url + * + * @param mixed $rawData raw data + * * @return string */ - protected function _avatar() + protected function _avatar($rawData) { - return self::FB_GRAPH_BASE_URL . Hash::get($this->_rawData, 'id') . '/picture?type=large'; + return self::FB_GRAPH_BASE_URL . Hash::get($rawData, 'id') . '/picture?type=large'; } } diff --git a/src/Social/Mapper/Google.php b/src/Social/Mapper/Google.php index c7bbfe551..e7dcf5923 100644 --- a/src/Social/Mapper/Google.php +++ b/src/Social/Mapper/Google.php @@ -34,10 +34,14 @@ class Google extends AbstractMapper ]; /** + * Get link property value + * + * @param mixed $rawData raw data + * * @return string */ - protected function _link() + protected function _link($rawData) { - return Hash::get($this->_rawData, $this->_mapFields['link']) ?: '#'; + return Hash::get($rawData, $this->_mapFields['link']) ?: '#'; } } diff --git a/src/Social/Mapper/Instagram.php b/src/Social/Mapper/Instagram.php index 44f8f9027..4478e2c61 100644 --- a/src/Social/Mapper/Instagram.php +++ b/src/Social/Mapper/Instagram.php @@ -34,10 +34,14 @@ class Instagram extends AbstractMapper ]; /** + * Get link property value + * + * @param mixed $rawData raw data + * * @return string */ - protected function _link() + protected function _link($rawData) { - return self::INSTAGRAM_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['username']); + return self::INSTAGRAM_BASE_URL . Hash::get($rawData, $this->_mapFields['username']); } } diff --git a/src/Social/Mapper/Twitter.php b/src/Social/Mapper/Twitter.php index 3ba6c5870..a4a2085fc 100644 --- a/src/Social/Mapper/Twitter.php +++ b/src/Social/Mapper/Twitter.php @@ -42,18 +42,26 @@ class Twitter extends AbstractMapper ]; /** + * Get link property value + * + * @param mixed $rawData raw data + * * @return string */ - protected function _link() + protected function _link($rawData) { - return self::TWITTER_BASE_URL . Hash::get($this->_rawData, $this->_mapFields['username']); + return self::TWITTER_BASE_URL . Hash::get($rawData, $this->_mapFields['username']); } /** + * Get avatar url + * + * @param mixed $rawData raw data + * * @return string */ - protected function _avatar() + protected function _avatar($rawData) { - return str_replace('normal', 'bigger', Hash::get($this->_rawData, $this->_mapFields['avatar'])); + return str_replace('normal', 'bigger', Hash::get($rawData, $this->_mapFields['avatar'])); } } From 71dcfb70000038755a409794fefd0ce48c639635 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 16:27:24 -0300 Subject: [PATCH 093/685] Social data mappers don't have $rawData property they expect an argument for invoke method --- tests/TestCase/Middleware/SocialEmailMiddlewareTest.php | 6 +++--- tests/TestCase/Social/Locator/DatabaseLocatorTest.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index 6671afb01..debc5391d 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -124,7 +124,7 @@ public function testWithGetRquest() 'token' => $Token, ] + $user->toArray(); - $user = (new Facebook($user))(); + $user = (new Facebook())($user); $user['provider'] = 'facebook'; $user['validated'] = true; Configure::write('Users.Email.validate', false); @@ -230,7 +230,7 @@ public function testSuccessfullyAuthenticated() 'token' => $Token, ] + $user->toArray(); - $user = (new Facebook($user))(); + $user = (new Facebook())($user); $user['provider'] = 'facebook'; $user['validated'] = true; Configure::write('Users.Email.validate', false); @@ -313,7 +313,7 @@ public function testWithoutEmail() 'token' => $Token, ] + $user->toArray(); - $user = (new Facebook($user))(); + $user = (new Facebook())($user); $user['provider'] = 'facebook'; $user['validated'] = true; Configure::write('Users.Email.validate', false); diff --git a/tests/TestCase/Social/Locator/DatabaseLocatorTest.php b/tests/TestCase/Social/Locator/DatabaseLocatorTest.php index d429a67de..a0d2e37a3 100644 --- a/tests/TestCase/Social/Locator/DatabaseLocatorTest.php +++ b/tests/TestCase/Social/Locator/DatabaseLocatorTest.php @@ -64,7 +64,7 @@ public function testGetOrCreate() 'cover_photo_url' => 'https://scontent.xx.fbcdn.net/v/test.jpg' ]; - $user = (new Facebook($data))(); + $user = (new Facebook())($data); $user['provider'] = 'facebook'; $this->Locator = new DatabaseLocator(); @@ -116,7 +116,7 @@ public function testGetOrCreateErrorSocialLogin() 'cover_photo_url' => 'https://scontent.xx.fbcdn.net/v/test.jpg' ]; - $user = (new Facebook($data))(); + $user = (new Facebook())($data); $user['provider'] = 'facebook'; $this->expectException(RecordNotFoundException::class); @@ -161,7 +161,7 @@ public function testGetOrCreateInvalidUserModel() $this->Locator = new DatabaseLocator([ 'userModel' => false ]); - $user = (new Facebook($data))(); + $user = (new Facebook())($data); $user['provider'] = 'facebook'; $this->expectException(InvalidSettingsException::class); From 1f99d741cae8bc2427e819a99ed01a78986756e1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 16:29:12 -0300 Subject: [PATCH 094/685] Social data mappers don't have $rawData property they expect an argument for invoke method --- src/Controller/Traits/LinkSocialTrait.php | 4 ++-- src/Middleware/SocialAuthMiddleware.php | 4 ++-- tests/TestCase/Controller/Traits/BaseTraitTest.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 26d2f5e0c..a1c3b5ed7 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -97,8 +97,8 @@ protected function _mapSocialUser($alias, $data) { $alias = ucfirst($alias); $providerMapperClass = "\\CakeDC\\Users\\Social\\Mapper\\$alias"; - $providerMapper = new $providerMapperClass($data); - $user = $providerMapper(); + $providerMapper = new $providerMapperClass(); + $user = $providerMapper($data); $user['provider'] = $alias; return $user; diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index a10ec29ba..27a9f3cee 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -182,8 +182,8 @@ protected function _mapUser($data) if (!class_exists($providerMapperClass)) { throw new \InvalidArgumentException(__("Provider mapper class {0} does not exist", $providerMapperClass)); } - $providerMapper = new $providerMapperClass($data); - $user = $providerMapper(); + $providerMapper = new $providerMapperClass(); + $user = $providerMapper($data); $user['provider'] = $this->service->getProviderName(); return $user; diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 0335531c2..8482d833f 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -11,10 +11,10 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use Authentication\AuthenticationService; use Authentication\Authenticator\Result; use Authentication\Controller\Component\AuthenticationComponent; use Authentication\Identity; +use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Model\Entity\User; use Cake\Controller\ComponentRegistry; use Cake\Controller\Controller; From d1b6101e6228632e6e28eff095ca6630ea67ed8f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 16:52:17 -0300 Subject: [PATCH 095/685] Refactored duplicated methods mapUser and mapSocialUser --- src/Controller/Traits/LinkSocialTrait.php | 22 +--------- src/Middleware/SocialAuthMiddleware.php | 23 +--------- src/Social/MapUser.php | 43 +++++++++++++++++++ .../Controller/Traits/LinkSocialTraitTest.php | 2 +- 4 files changed, 48 insertions(+), 42 deletions(-) create mode 100644 src/Social/MapUser.php diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index a1c3b5ed7..7f460b3a5 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller\Traits; +use CakeDC\Users\Social\MapUser; use CakeDC\Users\Social\Service\ServiceFactory; use Cake\Utility\Hash; @@ -60,7 +61,7 @@ public function callbackLinkSocial($alias = null) return $this->redirect(['action' => 'profile']); } $data = $server->getUser($this->request); - $data = $this->_mapSocialUser($alias, $data); + $data = (new MapUser())($server, $data); $userId = Hash::get($this->request->getAttribute('identity') ?? [], 'id'); $user = $this->getUsersTable()->get($userId); @@ -84,23 +85,4 @@ public function callbackLinkSocial($alias = null) 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. - * - * @return array - */ - protected function _mapSocialUser($alias, $data) - { - $alias = ucfirst($alias); - $providerMapperClass = "\\CakeDC\\Users\\Social\\Mapper\\$alias"; - $providerMapper = new $providerMapperClass(); - $user = $providerMapper($data); - $user['provider'] = $alias; - - return $user; - } } diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 27a9f3cee..b4d74b3e2 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -7,6 +7,7 @@ use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Plugin; use CakeDC\Users\Social\Locator\DatabaseLocator; +use CakeDC\Users\Social\MapUser; use CakeDC\Users\Social\Service\ServiceFactory; use Cake\Core\Configure; use Cake\Core\InstanceConfigTrait; @@ -124,8 +125,7 @@ protected function getUser(ServerRequest $request) { try { $rawData = $this->service->getUser($request); - - return $this->_mapUser($rawData); + return (new MapUser())($this->service, $rawData); } catch (\Exception $e) { $message = sprintf( "Error getting an access token / retrieving the authorized user's profile data. Error message: %s %s", @@ -169,23 +169,4 @@ protected function _touch(array $data) return false; } - - /** - * Map userdata with mapper defined at $providerConfig - * - * @param array $data User data - * @return mixed Either false or an array of user information - */ - protected function _mapUser($data) - { - $providerMapperClass = $this->service->getConfig('mapper'); - if (!class_exists($providerMapperClass)) { - throw new \InvalidArgumentException(__("Provider mapper class {0} does not exist", $providerMapperClass)); - } - $providerMapper = new $providerMapperClass(); - $user = $providerMapper($data); - $user['provider'] = $this->service->getProviderName(); - - return $user; - } } diff --git a/src/Social/MapUser.php b/src/Social/MapUser.php new file mode 100644 index 000000000..5a96c7422 --- /dev/null +++ b/src/Social/MapUser.php @@ -0,0 +1,43 @@ +getConfig('mapper'); + if (is_string($mapper)) { + $mapper = $this->buildMapper($mapper); + } + + $user = $mapper($data); + $user['provider'] = $service->getProviderName(); + + return $user; + } + + /** + * Build the mapper object + * + * @param string $className of mapper + * + * @return callable + */ + protected function buildMapper($className) + { + if (!class_exists($className)) { + throw new \InvalidArgumentException(__("Provider mapper class {0} does not exist", $className)); + } + + return new $className(); + } +} \ No newline at end of file diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 8008393f0..903fe4981 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -272,7 +272,7 @@ public function testCallbackLinkSocialHappy() $tokenExpires = $expiresTime->setTimestamp($Token->getExpires())->format('Y-m-d H:i:s'); $expected = [ - 'provider' => 'Facebook', + 'provider' => 'facebook', 'username' => 'mock_username', 'reference' => '9999911112255', 'avatar' => 'https://graph.facebook.com/9999911112255/picture?type=large', From 062fe8a8756542864ac2e1edc04a9b14e9a54992 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 17:04:03 -0300 Subject: [PATCH 096/685] RbacMiddleware config moved outside of plugin class --- config/users.php | 8 ++++++++ src/Plugin.php | 9 +-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/config/users.php b/config/users.php index c9ce8510c..20b80923a 100644 --- a/config/users.php +++ b/config/users.php @@ -205,6 +205,14 @@ ], 'AuthorizationComponent' => [ 'enabled' => true, + ], + 'RbacMiddleware' => [ + 'unauthorizedRedirect' => [ + 'prefix' => false, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + ] ] ], 'SocialAuthMiddleware' => [ diff --git a/src/Plugin.php b/src/Plugin.php index 360173a67..967763f3e 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -147,14 +147,7 @@ protected function addAuthorizationMiddleware(MiddlewareQueue $middlewareQueue) } if (Configure::read('Auth.Authorization.loadRbacMiddleware') !== false) { - $middlewareQueue->add(new RbacMiddleware(null, [ - 'unauthorizedRedirect' => [ - 'prefix' => false, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - ] - ])); + $middlewareQueue->add(new RbacMiddleware(null, Configure::read('Auth.RbacMiddleware'))); } return $middlewareQueue; From e046b2dc2640a17021ac0cdda49104d6282bce71 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 20 Oct 2018 17:31:18 -0300 Subject: [PATCH 097/685] phpcs fixes --- src/Controller/Traits/GoogleVerifyTrait.php | 2 +- src/Controller/Traits/LoginTrait.php | 2 +- src/Controller/UsersController.php | 2 +- src/Middleware/SocialAuthMiddleware.php | 1 + src/Social/MapUser.php | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Controller/Traits/GoogleVerifyTrait.php b/src/Controller/Traits/GoogleVerifyTrait.php index fa8f4342c..b03f1db2e 100644 --- a/src/Controller/Traits/GoogleVerifyTrait.php +++ b/src/Controller/Traits/GoogleVerifyTrait.php @@ -2,8 +2,8 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Core\Configure; use CakeDC\Users\Authentication\AuthenticationService; +use Cake\Core\Configure; trait GoogleVerifyTrait { diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 8f634965d..0d6b23da5 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -12,9 +12,9 @@ namespace CakeDC\Users\Controller\Traits; use Authentication\Authenticator\Result; +use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Authenticator\AuthenticatorFeedbackInterface; use CakeDC\Users\Authenticator\FormAuthenticator; -use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Plugin; use Cake\Core\Configure; diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index bc4c97262..16efa9055 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Controller; -use Cake\Core\Configure; use CakeDC\Users\Controller\Traits\GoogleVerifyTrait; use CakeDC\Users\Controller\Traits\LinkSocialTrait; use CakeDC\Users\Controller\Traits\LoginTrait; @@ -21,6 +20,7 @@ use CakeDC\Users\Controller\Traits\SimpleCrudTrait; use CakeDC\Users\Controller\Traits\SocialTrait; use CakeDC\Users\Model\Table\UsersTable; +use Cake\Core\Configure; /** * Users Controller diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index b4d74b3e2..0af9e268c 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -125,6 +125,7 @@ protected function getUser(ServerRequest $request) { try { $rawData = $this->service->getUser($request); + return (new MapUser())($this->service, $rawData); } catch (\Exception $e) { $message = sprintf( diff --git a/src/Social/MapUser.php b/src/Social/MapUser.php index 5a96c7422..284693b67 100644 --- a/src/Social/MapUser.php +++ b/src/Social/MapUser.php @@ -40,4 +40,4 @@ protected function buildMapper($className) return new $className(); } -} \ No newline at end of file +} From 84a14f815e2c4c0eb459964369c41985c8b228ec Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 21 Oct 2018 18:42:29 -0300 Subject: [PATCH 098/685] Refactoring social auth, added identifier --- src/Identifier/SocialIdentifier.php | 108 ++++++++++ .../Identifier/SocialIdentifierTest.php | 193 ++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 src/Identifier/SocialIdentifier.php create mode 100644 tests/TestCase/Identifier/SocialIdentifierTest.php diff --git a/src/Identifier/SocialIdentifier.php b/src/Identifier/SocialIdentifier.php new file mode 100644 index 000000000..94fd300cd --- /dev/null +++ b/src/Identifier/SocialIdentifier.php @@ -0,0 +1,108 @@ + 'Authentication.Orm', + 'authFinder' => 'all' + ]; + + /** + * Identifies an user or service by the passed credentials + * + * @param array $credentials Authentication credentials + * @return \ArrayAccess|array|null + */ + public function identify(array $credentials) + { + if (!isset($credentials['socialAuthUser'])) { + return null; + } + + $user = $this->createOrGetUser($credentials['socialAuthUser']); + + if (!$user) { + return null; + } + + $user = $this->findUser($user)->firstOrFail(); + + return $user; + } + + /** + * Get query object for fetching user from database. + * + * @param \Cake\Datasource\EntityInterface $user The user. + * + * @return \Cake\Orm\Query + */ + protected function findUser($user) + { + $table = $this->getUsersTable(); + $finder = $this->getConfig('authFinder'); + + $primaryKey = (array)$table->getPrimaryKey(); + + $conditions = []; + foreach ($primaryKey as $key) { + $conditions[$table->aliasField($key)] = $user->get($key); + } + + return $table->find($finder)->where($conditions); + } + + /** + * Create a new user or get if exists one for the social data + * + * @param mixed $data social data + * + * @return mixed + */ + protected function createOrGetUser($data) + { + $options = [ + 'use_email' => Configure::read('Users.Email.required'), + 'validate_email' => Configure::read('Users.Email.validate'), + 'token_expiration' => Configure::read('Users.Token.expiration') + ]; + + return $this->getUsersTable()->socialLogin($data, $options); + } + + /** + * Get users table based on internal config (usersTable) or users config (Users.table) + * + * @return \Cake\ORM\Table + */ + protected function getUsersTable() + { + $userModel = $this->getConfig('usersTable', Configure::read('Users.table')); + + return $this->getTableLocator()->get($userModel); + } +} diff --git a/tests/TestCase/Identifier/SocialIdentifierTest.php b/tests/TestCase/Identifier/SocialIdentifierTest.php new file mode 100644 index 000000000..d40afc8db --- /dev/null +++ b/tests/TestCase/Identifier/SocialIdentifierTest.php @@ -0,0 +1,193 @@ + '']; + $result = $identifier->identify($user); + $this->assertNull($result); + + $identifier = new SocialIdentifier([]); + + $user = []; + $result = $identifier->identify($user); + $this->assertNull($result); + } + + /** + * Test identify method + * + * @return void + */ + public function testIdentify() + { + $identifier = new SocialIdentifier([]); + + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $data = [ + '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' + ]; + + $user = (new Facebook())($data); + $user['provider'] = 'facebook'; + + $result = $identifier->identify(['socialAuthUser' => $user]); + $this->assertInstanceOf('CakeDC\Users\Model\Entity\User', $result); + $this->assertNotEmpty($result->id); + $this->assertEquals('test@gmail.com', $result->email); + $this->assertEquals('test', $result->username); + } + + /** + * Test identify method error in social login + * + * @return void + */ + public function testIdentifyErrorSocialLogin() + { + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $identifier = $this->getMockBuilder(SocialIdentifier::class)->setMethods([ + 'createOrGetUser' + ])->getMock(); + $identifier->expects($this->once()) + ->method('createOrGetUser') + ->will($this->returnValue(false)); + + $data = [ + 'token' => $Token, + 'id' => '1', + 'name' => '', + 'first_name' => 'Test', + 'last_name' => 'User', + 'email' => 'test@gmail.com', + 'hometown' => [ + 'id' => '108226049197930', + 'name' => 'Madrid' + ], + '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' + ]; + + $user = (new Facebook())($data); + $user['provider'] = 'facebook'; + + $result = $identifier->identify(['socialAuthUser' => $user]); + $this->assertNull($result); + } + + /** + * Test identify method no email + * + * @return void + */ + public function testIdentifyNoEmail() + { + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $data = [ + 'token' => $Token, + 'id' => '1', + 'name' => '', + 'first_name' => 'Test', + 'last_name' => 'User', + 'hometown' => [ + 'id' => '108226049197930', + 'name' => 'Madrid' + ], + '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' + ]; + + $identifier = new SocialIdentifier([]); + $user = (new Facebook())($data); + $user['provider'] = 'facebook'; + + $this->expectException(MissingEmailException::class); + $identifier->identify(['socialAuthUser' => $user]); + } +} From 398132a665550b14064fb43bc51e182ee36eae81 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 2 Nov 2018 11:22:22 -0300 Subject: [PATCH 099/685] Added social authenticator --- src/Authenticator/SocialAuthenticator.php | 125 +++++ .../SocialAuthenticationException.php | 19 + .../Authenticator/SocialAuthenticatorTest.php | 523 ++++++++++++++++++ 3 files changed, 667 insertions(+) create mode 100644 src/Authenticator/SocialAuthenticator.php create mode 100644 src/Exception/SocialAuthenticationException.php create mode 100644 tests/TestCase/Authenticator/SocialAuthenticatorTest.php diff --git a/src/Authenticator/SocialAuthenticator.php b/src/Authenticator/SocialAuthenticator.php new file mode 100644 index 000000000..ff45cae43 --- /dev/null +++ b/src/Authenticator/SocialAuthenticator.php @@ -0,0 +1,125 @@ + null, + 'urlChecker' => 'Authentication.Default', + ]; + + /** + * Prepares the error object for a login URL error + * + * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. + * @return \Authentication\Authenticator\ResultInterface + */ + protected function _buildLoginUrlErrorResult($request) + { + $errors = [ + sprintf( + 'Login URL `%s` did not match `%s`.', + (string)$request->getUri(), + implode('` or `', (array)$this->getConfig('loginUrl')) + ) + ]; + + return new Result(null, Result::FAILURE_OTHER, $errors); + } + + /** + * Authenticates the identity contained in a request. Will use the `config.userModel`, and `config.fields` + * to find POST data that is used to find a matching record in the `config.userModel`. Will return false if + * there is no post data, either username or password is missing, or if the scope conditions have not been met. + * + * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. + * @param \Psr\Http\Message\ResponseInterface $response Unused response object. + * @return \Authentication\Authenticator\ResultInterface + */ + public function authenticate(ServerRequestInterface $request, ResponseInterface $response) + { + $service = $request->getAttribute('socialService'); + if ($service === null) { + return new Result(null, Result::FAILURE_CREDENTIALS_MISSING); + } + + $rawData = $this->getRawData($request, $service); + if (empty($rawData)) { + return new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND); + } + + try { + $user = $this->getIdentifier()->identify(['socialAuthUser' => $rawData]); + if (!empty($user)) { + return new Result($user, Result::SUCCESS); + } + + return new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND); + + } catch ( + UserNotActiveException | + AccountNotActiveException | + MissingEmailException $exception + ) { + throw new SocialAuthenticationException(compact('rawData'), null, $exception); + } + } + + /** + * Get user raw data from social provider + * + * @param ServerRequestInterface $request request object + * @param ServiceInterface $service social service + * + * @return array|null + */ + protected function getRawData(ServerRequestInterface $request, ServiceInterface $service) + { + $rawData = null; + try { + $rawData = $service->getUser($request); + + return (new MapUser())($service, $rawData); + } catch (BadRequestException | \UnexpectedValueException $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 null; + } + } +} diff --git a/src/Exception/SocialAuthenticationException.php b/src/Exception/SocialAuthenticationException.php new file mode 100644 index 000000000..45341f479 --- /dev/null +++ b/src/Exception/SocialAuthenticationException.php @@ -0,0 +1,19 @@ +Provider = $this->getMockBuilder('\League\OAuth2\Client\Provider\Facebook')->setConstructorArgs([ + [ + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + [] + ])->setMethods([ + 'getAccessToken', 'getState', 'getAuthorizationUrl', 'getResourceOwner' + ])->getMock(); + + $config = [ + 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'className' => $this->Provider, + 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', + 'options' => [ + 'state' => '__TEST_STATE__', + 'graphApiVersion' => 'v2.8', + 'redirectUri' => '/auth/facebook', + 'linkSocialUri' => '/link-social/facebook', + 'callbackLinkSocialUri' => '/callback-link-social/facebook', + 'clientId' => '10003030300303', + 'clientSecret' => 'secretpassword' + ], + 'collaborators' => [], + 'signature' => null, + 'mapFields' => [], + 'path' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => null + ] + ]; + Configure::write('OAuth.providers.facebook', $config); + + $this->Request = ServerRequestFactory::fromGlobals(); + } + + /** + * Test authenticate method without social service + * + * @return void + */ + public function testAuthenticateNoSocialService() + { + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Request = $this->Request->withAttribute('params', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); + + $identifiers = new IdentifierCollection([ + 'CakeDC/Users.Social' + ]); + $Authenticator = new SocialAuthenticator($identifiers); + $Response = new Response(); + $result = $Authenticator->authenticate($this->Request, $Response); + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals(Result::FAILURE_CREDENTIALS_MISSING, $result->getStatus()); + $actual = $result->getData(); + $this->assertEmpty($actual); + } + + /** + * Test authenticate method with successfull authentication + * + * @return void + */ + public function testAuthenticateSuccessfullyAuthenticated() + { + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Request = $this->Request->withAttribute('params', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); + + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $user = new FacebookUser([ + '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' + ]); + + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); + + $this->Provider->expects($this->never()) + ->method('getState'); + + $this->Provider->expects($this->any()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo(['code' => 'ZPO9972j3092304230']) + ) + ->will($this->returnValue($Token)); + + $this->Provider->expects($this->any()) + ->method('getResourceOwner') + ->with( + $this->equalTo($Token) + ) + ->will($this->returnValue($user)); + + $service = (new ServiceFactory())->createFromProvider('facebook'); + $this->Request = $this->Request->withAttribute('socialService', $service); + $identifiers = new IdentifierCollection([ + 'CakeDC/Users.Social' + ]); + $Authenticator = new SocialAuthenticator($identifiers); + $Response = new Response(); + $result = $Authenticator->authenticate($this->Request, $Response); + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals(Result::SUCCESS, $result->getStatus()); + $actual = $result->getData(); + $this->assertInstanceOf(User::class, $actual); + $this->assertEquals('test@gmail.com', $actual->email); + } + + /** + * Test authenticate method with error, getRawData is null + * + * @return void + */ + public function testAuthenticateGetRawDataNull() + { + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Request = $this->Request->withAttribute('params', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); + + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $user = new FacebookUser([ + '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' + ]); + + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); + + $this->Provider->expects($this->never()) + ->method('getState'); + + $this->Provider->expects($this->any()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo(['code' => 'ZPO9972j3092304230']) + ) + ->will($this->returnValue($Token)); + + $this->Provider->expects($this->any()) + ->method('getResourceOwner') + ->with( + $this->equalTo($Token) + ) + ->will($this->throwException(new \UnexpectedValueException('User not found'))); + + $service = (new ServiceFactory())->createFromProvider('facebook'); + $this->Request = $this->Request->withAttribute('socialService', $service); + $identifiers = new IdentifierCollection([ + 'CakeDC/Users.Social' + ]); + $Authenticator = new SocialAuthenticator($identifiers); + $Response = new Response(); + $result = $Authenticator->authenticate($this->Request, $Response); + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals(Result::FAILURE_IDENTITY_NOT_FOUND, $result->getStatus()); + $actual = $result->getData(); + $this->assertEmpty($actual); + } + + /** + * Test authenticate method when social users does not have email + * + * @return void + */ + public function testAuthenticateErrorNoEmail() + { + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Request = $this->Request->withAttribute('params', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); + + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $user = new FacebookUser([ + 'id' => '1', + 'name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + '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' + ]); + + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); + + $this->Provider->expects($this->never()) + ->method('getState'); + + $this->Provider->expects($this->any()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo(['code' => 'ZPO9972j3092304230']) + ) + ->will($this->returnValue($Token)); + + $this->Provider->expects($this->any()) + ->method('getResourceOwner') + ->with( + $this->equalTo($Token) + ) + ->will($this->returnValue($user)); + + $service = (new ServiceFactory())->createFromProvider('facebook'); + $this->Request = $this->Request->withAttribute('socialService', $service); + $identifiers = new IdentifierCollection([ + 'CakeDC/Users.Social' + ]); + $Authenticator = new SocialAuthenticator($identifiers); + $Response = new Response(); + $result = false; + try { + $Authenticator->authenticate($this->Request, $Response); + } catch (SocialAuthenticationException $e) { + $rawData = ['token' => $Token] + $user->toArray(); + $expected = [ + 'rawData' => (new MapUser())($service, $rawData) + ]; + $actual = $e->getAttributes(); + $this->assertEquals($expected, $actual); + $this->assertEquals(400, $e->getCode()); + + $this->assertInstanceOf(MissingEmailException::class, $e->getPrevious()); + $result = true; + } + $this->assertTrue($result); + } + + /** + * Test authenticate method when social identifier return null + * + * @return void + */ + public function testAuthenticateIdentifierReturnedNull() + { + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Request = $this->Request->withAttribute('params', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); + + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $user = new FacebookUser([ + 'id' => '1', + 'name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + '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' + ]); + + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); + + $this->Provider->expects($this->never()) + ->method('getState'); + + $this->Provider->expects($this->any()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo(['code' => 'ZPO9972j3092304230']) + ) + ->will($this->returnValue($Token)); + + $this->Provider->expects($this->any()) + ->method('getResourceOwner') + ->with( + $this->equalTo($Token) + ) + ->will($this->returnValue($user)); + + $service = (new ServiceFactory())->createFromProvider('facebook'); + $this->Request = $this->Request->withAttribute('socialService', $service); + $identifiers = new IdentifierCollection([]); + $Authenticator = new SocialAuthenticator($identifiers); + $Response = new Response(); + $Authenticator->authenticate($this->Request, $Response); + $result = $Authenticator->authenticate($this->Request, $Response); + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals(Result::FAILURE_IDENTITY_NOT_FOUND, $result->getStatus()); + $actual = $result->getData(); + $this->assertEmpty($actual); + } +} \ No newline at end of file From 2b35027aa5418ab0c21e1d7bf4b2e5aa91c707f7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 2 Nov 2018 12:16:10 -0300 Subject: [PATCH 100/685] Refactor for multiple catch arguments --- src/Authenticator/SocialAuthenticator.php | 51 ++++++++++++++++++----- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/src/Authenticator/SocialAuthenticator.php b/src/Authenticator/SocialAuthenticator.php index ff45cae43..74c763bb2 100644 --- a/src/Authenticator/SocialAuthenticator.php +++ b/src/Authenticator/SocialAuthenticator.php @@ -65,8 +65,16 @@ protected function _buildLoginUrlErrorResult($request) * * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. * @param \Psr\Http\Message\ResponseInterface $response Unused response object. + * @throws \Exception + * @throws SocialAuthenticationException * @return \Authentication\Authenticator\ResultInterface */ + /** + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @return Result|\Authentication\Authenticator\ResultInterface + * @throws \Exception + */ public function authenticate(ServerRequestInterface $request, ResponseInterface $response) { $service = $request->getAttribute('socialService'); @@ -87,13 +95,17 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface return new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND); - } catch ( - UserNotActiveException | - AccountNotActiveException | - MissingEmailException $exception - ) { + } catch (\Exception $exception) { + $list = [ + UserNotActiveException::class, + AccountNotActiveException::class, + MissingEmailException::class + ]; + $this->throwIfNotInlist($exception, $list); + throw new SocialAuthenticationException(compact('rawData'), null, $exception); } + } /** @@ -101,25 +113,44 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface * * @param ServerRequestInterface $request request object * @param ServiceInterface $service social service - * + * @throws \Exception * @return array|null */ - protected function getRawData(ServerRequestInterface $request, ServiceInterface $service) + private function getRawData(ServerRequestInterface $request, ServiceInterface $service) { $rawData = null; try { $rawData = $service->getUser($request); return (new MapUser())($service, $rawData); - } catch (BadRequestException | \UnexpectedValueException $e) { + } catch (\Exception $exception) { + $list = [BadRequestException::class, \UnexpectedValueException::class]; + $this->throwIfNotInlist($exception, $list); $message = sprintf( "Error getting an access token / retrieving the authorized user's profile data. Error message: %s %s", - $e->getMessage(), - $e + $exception->getMessage(), + $exception ); $this->log($message); return null; + + } + } + + /** + * Throw the exception if not in the list + * + * @param \Exception $exception exception thrown + * @param array $allowed list of allowed exception classes + * @throws \Exception + * @return void + */ + private function throwIfNotInlist(\Exception $exception, array $list) + { + $className = get_class($exception); + if (!in_array($className, $list)) { + throw $exception; } } } From 869d59f2bda9f9b2fc8c313d43db3fcdd59419ff Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 2 Nov 2018 16:57:15 -0300 Subject: [PATCH 101/685] Social authenticator with FAILURE_ACCOUNT_NOT_ACTIVE and FAILURE_USER_NOT_ACTIVE --- src/Authenticator/SocialAuthenticator.php | 21 ++-- .../Authenticator/SocialAuthenticatorTest.php | 119 ++++++++++++++++++ 2 files changed, 130 insertions(+), 10 deletions(-) diff --git a/src/Authenticator/SocialAuthenticator.php b/src/Authenticator/SocialAuthenticator.php index 74c763bb2..7a6eefcc3 100644 --- a/src/Authenticator/SocialAuthenticator.php +++ b/src/Authenticator/SocialAuthenticator.php @@ -26,6 +26,11 @@ class SocialAuthenticator extends AbstractAuthenticator use UrlCheckerTrait; use LogTrait; + const SOCIAL_SERVICE_ATTRIBUTE = 'socialService'; + + const FAILURE_ACCOUNT_NOT_ACTIVE = 'FAILURE_ACCOUNT_NOT_ACTIVE'; + + const FAILURE_USER_NOT_ACTIVE = 'FAILURE_USER_NOT_ACTIVE'; /** * Default config for this object. * - `fields` The fields to use to identify a user by. @@ -77,7 +82,7 @@ protected function _buildLoginUrlErrorResult($request) */ public function authenticate(ServerRequestInterface $request, ResponseInterface $response) { - $service = $request->getAttribute('socialService'); + $service = $request->getAttribute(self::SOCIAL_SERVICE_ATTRIBUTE); if ($service === null) { return new Result(null, Result::FAILURE_CREDENTIALS_MISSING); } @@ -95,17 +100,13 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface return new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND); - } catch (\Exception $exception) { - $list = [ - UserNotActiveException::class, - AccountNotActiveException::class, - MissingEmailException::class - ]; - $this->throwIfNotInlist($exception, $list); - + } catch(AccountNotActiveException $e) { + return new Result(null, self::FAILURE_ACCOUNT_NOT_ACTIVE); + } catch(UserNotActiveException $e) { + return new Result(null, self::FAILURE_USER_NOT_ACTIVE); + } catch (MissingEmailException $exception) { throw new SocialAuthenticationException(compact('rawData'), null, $exception); } - } /** diff --git a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php index be8139144..9b4397d40 100644 --- a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php @@ -17,8 +17,10 @@ use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; use CakeDC\Users\Authenticator\SocialAuthenticator; +use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\SocialAuthenticationException; +use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Model\Entity\User; use CakeDC\Users\Social\Mapper\Facebook; use CakeDC\Users\Social\MapUser; @@ -520,4 +522,121 @@ public function testAuthenticateIdentifierReturnedNull() $actual = $result->getData(); $this->assertEmpty($actual); } + + /** + * Data provider for testAuthenticateErrorException + * @return array + */ + public function dataProviderAuthenticateErrorException() + { + return [ + [ + new AccountNotActiveException('Not Active'), + SocialAuthenticator::FAILURE_ACCOUNT_NOT_ACTIVE + ], + [ + new UserNotActiveException('Not Active'), + SocialAuthenticator::FAILURE_USER_NOT_ACTIVE + ] + ]; + } + /** + * Test authenticate method with successfull authentication + * + * @param \Exception $exception thrown exception + * @param string $status expected status from Result object + * + * @dataProvider dataProviderAuthenticateErrorException + * @return void + */ + public function testAuthenticateErrorException($exception, $status) + { + $uri = new Uri('/auth/facebook'); + $this->Request = $this->Request->withUri($uri); + $this->Request = $this->Request->withQueryParams([ + 'code' => 'ZPO9972j3092304230', + 'state' => '__TEST_STATE__' + ]); + $this->Request = $this->Request->withAttribute('params', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'provider' => 'facebook' + ]); + $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); + + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $user = new FacebookUser([ + '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' + ]); + + $this->Provider->expects($this->never()) + ->method('getAuthorizationUrl'); + + $this->Provider->expects($this->never()) + ->method('getState'); + + $this->Provider->expects($this->any()) + ->method('getAccessToken') + ->with( + $this->equalTo('authorization_code'), + $this->equalTo(['code' => 'ZPO9972j3092304230']) + ) + ->will($this->returnValue($Token)); + + $this->Provider->expects($this->any()) + ->method('getResourceOwner') + ->with( + $this->equalTo($Token) + ) + ->will($this->returnValue($user)); + + $service = (new ServiceFactory())->createFromProvider('facebook'); + $this->Request = $this->Request->withAttribute('socialService', $service); + $identifiers = $this->getMockBuilder(IdentifierCollection::class, ['identify'])->getMock(); + $identifiers->expects($this->once()) + ->method('identify') + ->will($this->throwException($exception)); + + $Authenticator = new SocialAuthenticator($identifiers); + $Response = new Response(); + $result = $Authenticator->authenticate($this->Request, $Response); + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals($status, $result->getStatus()); + $actual = $result->getData(); + $this->assertEmpty($actual); + } } \ No newline at end of file From 19537ac35f8bbd7e14fcade343935f4d1a288024 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 2 Nov 2018 16:58:04 -0300 Subject: [PATCH 102/685] Cleanup social auth middleware --- src/Middleware/SocialAuthMiddleware.php | 132 +++++------ .../Middleware/SocialAuthMiddlewareTest.php | 205 ++++++++++++------ 2 files changed, 195 insertions(+), 142 deletions(-) diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 0af9e268c..e16ec7867 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -2,8 +2,11 @@ namespace CakeDC\Users\Middleware; +use Cake\Routing\Router; +use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; +use CakeDC\Users\Exception\SocialAuthenticationException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Plugin; use CakeDC\Users\Social\Locator\DatabaseLocator; @@ -42,6 +45,12 @@ class SocialAuthMiddleware */ protected $service; + protected $params = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin' + ]; + /** * Perform social auth * @@ -57,117 +66,78 @@ public function __invoke(ServerRequest $request, ResponseInterface $response, $n return $next($request, $response); } - $this->setConfig(Configure::read('SocialAuthMiddleware')); - - $this->service = (new ServiceFactory())->createFromRequest($request); - if (!$this->service->isGetUserStep($request)) { - return $response->withLocation($this->service->getAuthorizationUrl($request)); + $service = (new ServiceFactory())->createFromRequest($request); + if (!$service->isGetUserStep($request)) { + return $response->withLocation($service->getAuthorizationUrl($request)); } + $request = $request->withAttribute(SocialAuthenticator::SOCIAL_SERVICE_ATTRIBUTE, $service); - return $this->finishWithResult($this->authenticate($request), $request, $response, $next); + try { + return $next($request, $response); + } catch (SocialAuthenticationException $exception) { + return $this->onAuthenticationException($request, $response, $exception); + } } /** - * finish middleware process. + * Handle SocialAuthenticationException * - * @param int $result authentication result * @param \Psr\Http\Message\ServerRequestInterface $request The request. * @param \Psr\Http\Message\ResponseInterface $response The response. - * @param callable $next Callback to invoke the next middleware. + * @param \CakeDC\Users\Exception\SocialAuthenticationException $exception Exception thrown + * * @return \Psr\Http\Message\ResponseInterface A response */ - protected function finishWithResult($result, ServerRequest $request, ResponseInterface $response, $next) + protected function onAuthenticationException(ServerRequest $request, ResponseInterface $response, $exception) { - if ($result) { - $this->authStatus = self::AUTH_SUCCESS; + $baseClassName = get_class($exception->getPrevious()); + if ($baseClassName === MissingEmailException::class) { + $this->setErrorMessage($request, __d('CakeDC/Users', 'Please enter your email')); + $request->getSession()->write( - $this->getConfig('sessionAuthKey'), - $result + Configure::read('Users.Key.Session.social'), + $exception->getAttributes()['rawData'] ); - $request->getSession()->delete(Configure::read('Users.Key.Session.social')); - $request->getSession()->write('Users.successSocialLogin', true); + return $this->responseWithActionLocation($response, 'socialEmail'); } - $request = $request->withAttribute(self::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS, $this->authStatus); - $request = $request->withAttribute(self::ATTRIBUTE_NAME_SOCIAL_RAW_DATA, $this->rawData); + $this->setErrorMessage($request, __d('CakeDC/Users', 'Could not identify your account, please try again')); - return $next($request, $response); + return $this->responseWithActionLocation($response, 'login'); } /** - * Get a user based on information in the request. + * Set request error message * - * @param \Cake\Http\ServerRequest $request Request object. - * @return bool - * @throws \RuntimeException If the `CakeDC/Users/OAuth2.newUser` event is missing or returns empty. - */ - protected function authenticate(ServerRequest $request) - { - $user = $this->getUser($request); - if (!$user) { - return false; - } - - $this->rawData = $user; - - return $this->_touch($user); - } - - /** - * Authenticates with OAuth provider by getting an access token and - * retrieving the authorized user's profile data. + * @param ServerRequest $request the request with session attribute + * @param string $message the message * - * @param \Cake\Http\ServerRequest $request Request object. - * @return array|bool + * @return void */ - protected function getUser(ServerRequest $request) + private function setErrorMessage(ServerRequest $request, $message) { - try { - $rawData = $this->service->getUser($request); - - return (new MapUser())($this->service, $rawData); - } 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; - } + $messages = (array)$request->getSession()->read('Flash.flash'); + $messages[] = [ + 'key' => 'flash', + 'element' => 'error', + 'params' => [], + $message + ]; + $request->getSession()->write('Flash.flash', $messages); } /** - * Find or create local user + * Set location header to response using the string action * - * @param array $data data - * @return array|bool|mixed - * @throws MissingEmailException + * @param ResponseInterface $response to set location header + * @param string $action action at users controller + * @return ResponseInterface */ - protected function _touch(array $data) + protected function responseWithActionLocation(ResponseInterface $response, $action) { - $locator = new DatabaseLocator($this->getConfig('locator')); - try { - return $locator->getOrCreate($data); - } catch (UserNotActiveException $ex) { - $this->authStatus = self::AUTH_ERROR_USER_NOT_ACTIVE; - $exception = $ex; - } catch (AccountNotActiveException $ex) { - $this->authStatus = self::AUTH_ERROR_ACCOUNT_NOT_ACTIVE; - $exception = $ex; - } catch (MissingEmailException $ex) { - $this->authStatus = self::AUTH_ERROR_MISSING_EMAIL; - $exception = $ex; - } catch (RecordNotFoundException $ex) { - $this->authStatus = self::AUTH_ERROR_FIND_USER; - $exception = $ex; - } - - $args = ['exception' => $exception, 'rawData' => $data]; - $this->dispatchEvent(Plugin::EVENT_FAILED_SOCIAL_LOGIN, $args); + $url = Router::url(compact('action') + $this->params); - return false; + return $response->withLocation($url); } } diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index cf44a2309..ebcec49c7 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -8,12 +8,21 @@ namespace CakeDC\Users\Test\TestCase\Middleware; +use Cake\Http\ServerRequest; +use CakeDC\Users\Exception\AccountNotActiveException; +use CakeDC\Users\Exception\MissingEmailException; +use CakeDC\Users\Exception\SocialAuthenticationException; +use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Model\Entity\User; use Cake\Core\Configure; use Cake\Http\Response; use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; +use CakeDC\Users\Social\MapUser; +use CakeDC\Users\Social\Service\OAuth2Service; +use CakeDC\Users\Social\Service\ServiceFactory; +use Doctrine\Instantiator\Exception\UnexpectedValueException; use League\OAuth2\Client\Provider\FacebookUser; use Zend\Diactoros\Uri; @@ -147,7 +156,7 @@ public function testProceedStepOne() } /** - * Test when user successfully authenticated + * Test when user is on get user step * * @return void */ @@ -205,48 +214,75 @@ public function testSuccessfullyAuthenticated() 'cover_photo_url' => 'https://scontent.xx.fbcdn.net/v/test.jpg' ]); - $this->Provider->expects($this->never()) - ->method('getAuthorizationUrl'); - - $this->Provider->expects($this->never()) - ->method('getState'); - - $this->Provider->expects($this->any()) - ->method('getAccessToken') - ->with( - $this->equalTo('authorization_code'), - $this->equalTo(['code' => 'ZPO9972j3092304230']) - ) - ->will($this->returnValue($Token)); - - $this->Provider->expects($this->any()) - ->method('getResourceOwner') - ->with( - $this->equalTo($Token) - ) - ->will($this->returnValue($user)); - $Middleware = new SocialAuthMiddleware(); - $response = new Response(); - $next = function ($request, $response) { - return compact('request', 'response'); + $ResponseOriginal = new Response(); + $checked = false; + $next = function (ServerRequest $request, Response $response) use ($ResponseOriginal, &$checked) { + /** + * @var OAuth2Service $service + */ + $service = $request->getAttribute('socialService'); + $this->assertInstanceOf(OAuth2Service::class, $service); + $this->assertEquals('facebook', $service->getProviderName()); + $this->assertTrue($service->isGetUserStep($request)); + $this->assertSame($response, $ResponseOriginal); + $checked = true; + + return $response; }; + $result = $Middleware($this->Request, $ResponseOriginal, $next); + $this->assertSame($result, $ResponseOriginal); + $this->assertTrue($checked); + } - $result = $Middleware($this->Request, $response, $next); - $this->assertEquals(SocialAuthMiddleware::AUTH_SUCCESS, $result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS)); - $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); - $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)['id']); - $this->assertInstanceOf(User::class, $this->Request->getSession()->read('Auth')); - $this->assertEquals(200, $result['response']->getStatusCode()); + /** + * Data provider for testSocialAuthenticationException + * + * @return array + */ + public function dataProviderSocialAuthenticationException() + { + $missingEmail = [ + new MissingEmailException("Missing email"), + [ + 'key' => 'flash', + 'element' => 'error', + 'params' => [], + __d('CakeDC/Users', 'Please enter your email') + ], + '/users/users/social-email', + true, + ]; + $unknown = [ + new UnexpectedValueException("User not active"), + [ + 'key' => 'flash', + 'element' => 'error', + 'params' => [], + __d('CakeDC/Users', 'Could not identify your account, please try again') + ], + '/login', + false + ]; + + return [ + $missingEmail, + $unknown + ]; } /** * Test when has error getting user * + * @param \Exception $previousException previous exception used on SocialAuthenticationException + * @param array $flash flash that should be on session + * @param array $location value of location header that should be on request + * @param bool $keepSocialUser should keed a raw data of social user + * @dataProvider dataProviderSocialAuthenticationException * @return void */ - public function testErrorGetUser() + public function testSocialAuthenticationException($previousException, $flash, $location, $keepSocialUser) { $uri = new Uri('/auth/facebook'); $this->Request = $this->Request->withUri($uri); @@ -262,41 +298,88 @@ public function testErrorGetUser() ]); $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); + $Middleware = new SocialAuthMiddleware(); + + $ResponseOriginal = new Response(); + $checked = false; + + $service = (new ServiceFactory())->createFromProvider('facebook'); $Token = new \League\OAuth2\Client\Token\AccessToken([ 'access_token' => 'test-token', 'expires' => 1490988496 ]); - - $this->Provider->expects($this->never()) - ->method('getAuthorizationUrl'); - - $this->Provider->expects($this->never()) - ->method('getState'); - - $this->Provider->expects($this->any()) - ->method('getAccessToken') - ->with( - $this->equalTo('authorization_code'), - $this->equalTo(['code' => 'ZPO9972j3092304230']) - ) - ->will($this->returnValue($Token)); - - $this->Provider->expects($this->any()) - ->method('getResourceOwner') - ->will($this->throwException(new \Exception('Test error'))); - - $Middleware = new SocialAuthMiddleware(); - - $response = new Response(); - $next = function ($request, $response) { - return compact('request', 'response'); + $user = new FacebookUser([ + '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' + ]); + $user = ['token' => $Token] + $user->toArray(); + $rawData = (new MapUser())($service, $user); + $next = function (ServerRequest $request, Response $response) use ($previousException, $ResponseOriginal, &$checked, $rawData) { + /** + * @var OAuth2Service $service + */ + $service = $request->getAttribute('socialService'); + $this->assertInstanceOf(OAuth2Service::class, $service); + $this->assertEquals('facebook', $service->getProviderName()); + $this->assertTrue($service->isGetUserStep($request)); + $this->assertSame($response, $ResponseOriginal); + $checked = true; + + throw new SocialAuthenticationException( + [ + 'rawData' => $rawData + ], + null, + $previousException + ); }; + /** + * @var Response $result + */ + $result = $Middleware($this->Request, $ResponseOriginal, $next); + $this->assertInstanceOf(Response::class, $result); + $actual = $result->getHeader('Location'); + $expected = [$location]; + $this->assertEquals($expected, $actual); + $expected = [ + $flash + ]; + $actual = $this->Request->getSession()->read('Flash.flash'); + $this->assertEquals($expected, $actual); - $result = $Middleware($this->Request, $response, $next); - $this->assertEquals(0, $result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS)); - $this->assertEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); - $this->assertEmpty($this->Request->getSession()->read('Auth')); - $this->assertEquals(200, $result['response']->getStatusCode()); + if ($keepSocialUser) { + $actual = $this->Request->getSession()->read(Configure::read('Users.Key.Session.social')); + $expected = (new MapUser())($service, $user); + $this->assertEquals($expected, $actual); + } } /** From 7aca6c23e46a7963184e4969b204c046cce885ce Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 2 Nov 2018 18:06:27 -0300 Subject: [PATCH 103/685] social pending email authenticator --- src/Authenticator/SocialAuthTrait.php | 47 +++++ src/Authenticator/SocialAuthenticator.php | 19 +- .../SocialPendingEmailAuthenticator.php | 102 +++++++++ .../SocialPendingEmailAuthenticatorTest.php | 195 ++++++++++++++++++ 4 files changed, 347 insertions(+), 16 deletions(-) create mode 100644 src/Authenticator/SocialAuthTrait.php create mode 100644 src/Authenticator/SocialPendingEmailAuthenticator.php create mode 100644 tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php diff --git a/src/Authenticator/SocialAuthTrait.php b/src/Authenticator/SocialAuthTrait.php new file mode 100644 index 000000000..061657325 --- /dev/null +++ b/src/Authenticator/SocialAuthTrait.php @@ -0,0 +1,47 @@ +getIdentifier()->identify(['socialAuthUser' => $rawData]); + if (!empty($user)) { + return new Result($user, Result::SUCCESS); + } + + return new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND); + + } catch(AccountNotActiveException $e) { + return new Result(null, self::FAILURE_ACCOUNT_NOT_ACTIVE); + } catch(UserNotActiveException $e) { + return new Result(null, self::FAILURE_USER_NOT_ACTIVE); + } catch (MissingEmailException $exception) { + throw new SocialAuthenticationException(compact('rawData'), null, $exception); + } + } + +} \ No newline at end of file diff --git a/src/Authenticator/SocialAuthenticator.php b/src/Authenticator/SocialAuthenticator.php index 7a6eefcc3..7528d6c6a 100644 --- a/src/Authenticator/SocialAuthenticator.php +++ b/src/Authenticator/SocialAuthenticator.php @@ -23,8 +23,9 @@ */ class SocialAuthenticator extends AbstractAuthenticator { - use UrlCheckerTrait; use LogTrait; + use SocialAuthTrait; + use UrlCheckerTrait; const SOCIAL_SERVICE_ATTRIBUTE = 'socialService'; @@ -92,21 +93,7 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface return new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND); } - try { - $user = $this->getIdentifier()->identify(['socialAuthUser' => $rawData]); - if (!empty($user)) { - return new Result($user, Result::SUCCESS); - } - - return new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND); - - } catch(AccountNotActiveException $e) { - return new Result(null, self::FAILURE_ACCOUNT_NOT_ACTIVE); - } catch(UserNotActiveException $e) { - return new Result(null, self::FAILURE_USER_NOT_ACTIVE); - } catch (MissingEmailException $exception) { - throw new SocialAuthenticationException(compact('rawData'), null, $exception); - } + return $this->identify($rawData); } /** diff --git a/src/Authenticator/SocialPendingEmailAuthenticator.php b/src/Authenticator/SocialPendingEmailAuthenticator.php new file mode 100644 index 000000000..0d4f36a43 --- /dev/null +++ b/src/Authenticator/SocialPendingEmailAuthenticator.php @@ -0,0 +1,102 @@ + [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialEmail' + ], + 'urlChecker' => 'Authentication.CakeRouter', + ]; + + /** + * Prepares the error object for a login URL error + * + * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. + * @return \Authentication\Authenticator\ResultInterface + */ + protected function _buildLoginUrlErrorResult($request) + { + $errors = [ + sprintf( + 'Login URL `%s` did not match `%s`.', + (string)$request->getUri(), + implode('` or `', (array)$this->getConfig('loginUrl')) + ) + ]; + + return new Result(null, Result::FAILURE_OTHER, $errors); + } + + /** + * Authenticates the identity contained in a request. Will use the `config.userModel`, and `config.fields` + * to find POST data that is used to find a matching record in the `config.userModel`. Will return false if + * there is no post data, either username or password is missing, or if the scope conditions have not been met. + * + * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. + * @param \Psr\Http\Message\ResponseInterface $response Unused response object. + * @return \Authentication\Authenticator\ResultInterface + */ + public function authenticate(ServerRequestInterface $request, ResponseInterface $response) + { + if (!$this->_checkUrl($request)) { + return $this->_buildLoginUrlErrorResult($request); + } + $rawData = $request->getSession()->read(Configure::read('Users.Key.Session.social')); + $body = $request->getParsedBody(); + $email = Hash::get($body, 'email'); + if (empty($rawData) || empty($email)) { + return new Result(null, Result::FAILURE_CREDENTIALS_MISSING); + } + $captcha = Hash::get($body, 'g-recaptcha-response'); + if (!$this->validateReCaptcha($captcha, $request->clientIp())) { + return new Result(null, self::FAILURE_INVALID_RECAPTCHA); + } + + $rawData['email'] = $email; + + return $this->identify($rawData); + } +} diff --git a/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php new file mode 100644 index 000000000..097f7fd9c --- /dev/null +++ b/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php @@ -0,0 +1,195 @@ +Request = ServerRequestFactory::fromGlobals(); + } + + /** + * testAuthenticate + * + * @return void + */ + public function testAuthenticateBaseFailed() + { + $user = $this->getUserData(); + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/users/users/social-email'], + [], + ['email' => 'testAuthenticateBaseFailed@example.com', 'g-recaptcha-response' => 'BD-S2333-156465897897'] + ); + $requestNoEmail = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/users/users/social-email'], + [], + [] + ); + Configure::write('Users.Email.validate', false); + $request->getSession()->write(Configure::read('Users.Key.Session.social'), $user); + $requestNoEmail->getSession()->write(Configure::read('Users.Key.Session.social'), $user); + $Response = new Response(); + $identifiers = new IdentifierCollection([ + 'CakeDC/Users.Social' + ]); + $Authenticator = new SocialPendingEmailAuthenticator($identifiers); + $result = $Authenticator->authenticate($requestNoEmail, $Response); + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals(Result::FAILURE_CREDENTIALS_MISSING, $result->getStatus()); + + $Authenticator = $this->getMockBuilder(SocialPendingEmailAuthenticator::class)->setConstructorArgs([ + $identifiers + ])->setMethods(['validateReCaptcha'])->getMock(); + + $Authenticator->expects($this->once()) + ->method('validateReCaptcha') + ->with( + $this->equalTo('BD-S2333-156465897897') + ) + ->will($this->returnValue(true)); + $result = $Authenticator->authenticate($request, $Response); + + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals(Result::SUCCESS, $result->getStatus()); + $data = $result->getData(); + $this->assertInstanceOf(User::class, $data); + $this->assertEquals('testAuthenticateBaseFailed@example.com', $data['email']); + } + + /** + * testAuthenticate + * + * @return void + */ + public function testAuthenticateInvalidRecaptcha() + { + $identifiers = new IdentifierCollection([ + 'Authentication.Password' + ]); + + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/users/users/social-email'], + [], + ['email' => 'testAuthenticateBaseFailed@example.com', 'g-recaptcha-response' => 'BD-S2333-156465897897'] + ); + $response = new Response(); + + $Authenticator = $this->getMockBuilder(SocialPendingEmailAuthenticator::class)->setConstructorArgs([ + $identifiers + ])->setMethods(['validateReCaptcha'])->getMock(); + + $Authenticator->expects($this->once()) + ->method('validateReCaptcha') + ->with( + $this->equalTo('BD-S2333-156465897897') + ) + ->will($this->returnValue(false)); + + $user = $this->getUserData(); + Configure::write('Users.reCaptcha.login', true); + Configure::write('Users.Email.validate', false); + $request->getSession()->write(Configure::read('Users.Key.Session.social'), $user); + $result = $Authenticator->authenticate($request, $response); + $this->assertInstanceOf(Result::class, $result); + $this->assertEquals(SocialPendingEmailAuthenticator::FAILURE_INVALID_RECAPTCHA, $result->getStatus()); + $this->assertNull($result->getData()); + } + + /** + * Get social user data for test + * + * @return mixed + */ + protected function getUserData() + { + $Token = new \League\OAuth2\Client\Token\AccessToken([ + 'access_token' => 'test-token', + 'expires' => 1490988496 + ]); + + $data = [ + 'token' => $Token, + 'id' => '1', + 'name' => 'Test User', + 'first_name' => 'Test', + 'last_name' => 'User', + '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' + ]; + + $user = (new Facebook())($data); + $user['provider'] = 'facebook'; + $user['validated'] = true; + + return $user; + } +} From 7c95302a94446febce722216a1c961a5d014dacd Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 2 Nov 2018 18:23:49 -0300 Subject: [PATCH 104/685] refactored social email middleware --- src/Middleware/SocialEmailMiddleware.php | 67 ++++-------------------- 1 file changed, 9 insertions(+), 58 deletions(-) diff --git a/src/Middleware/SocialEmailMiddleware.php b/src/Middleware/SocialEmailMiddleware.php index 7f6af585a..0076353bb 100644 --- a/src/Middleware/SocialEmailMiddleware.php +++ b/src/Middleware/SocialEmailMiddleware.php @@ -6,6 +6,7 @@ use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequest; +use CakeDC\Users\Exception\SocialAuthenticationException; use Psr\Http\Message\ResponseInterface; class SocialEmailMiddleware extends SocialAuthMiddleware @@ -22,13 +23,14 @@ class SocialEmailMiddleware extends SocialAuthMiddleware */ public function __invoke(ServerRequest $request, ResponseInterface $response, $next) { + if ($request->getAttribute('identity')) { + $request->getSession()->delete(Configure::read('Users.Key.Session.social')); + } $action = $request->getParam('action'); if ($action !== 'socialEmail' || $request->getParam('plugin') !== 'CakeDC/Users') { return $next($request, $response); } - $this->setConfig(Configure::read('SocialAuthMiddleware')); - return $this->handleAction($request, $response, $next); } @@ -37,7 +39,7 @@ public function __invoke(ServerRequest $request, ResponseInterface $response, $n * * @param int $request authentication result * @param \Psr\Http\Message\ServerRequestInterface $response The request. - * @param \Psr\Http\Message\ResponseInterface $next The response. + * @param callable $next The response. * @return \Psr\Http\Message\ResponseInterface A response */ private function handleAction(ServerRequest $request, ResponseInterface $response, $next) @@ -45,61 +47,10 @@ private function handleAction(ServerRequest $request, ResponseInterface $respons if (!$request->getSession()->check(Configure::read('Users.Key.Session.social'))) { throw new NotFoundException(); } - $request->getSession()->delete('Flash.auth'); - $result = false; - - if (!$request->is('post')) { - return $this->finishWithResult($result, $request, $response, $next); - } - - if (!$this->_validateRegisterPost($request)) { - $this->authStatus = self::AUTH_ERROR_INVALID_RECAPTCHA; - } else { - $result = $this->authenticate($request); - } - - return $this->finishWithResult($result, $request, $response, $next); - } - - /** - * Check the POST and validate it for registration, for now we check the reCaptcha - * - * @param \Psr\Http\Message\ServerRequestInterface $request The request. - * @return bool - */ - private function _validateRegisterPost($request) - { - if (!Configure::read('Users.reCaptcha.registration')) { - return true; - } - - return $this->validateReCaptcha( - $request->getData('g-recaptcha-response'), - $request->clientIp() - ); - } - - /** - * Authenticates with Session data (from SocialAuthMiddleware) and form email. - * config: Users.Key.Session.social, - * form input name: email - * - * @param \Cake\Http\ServerRequest $request Request object. - * @return array|bool - */ - protected 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; - } - $request->getSession()->delete(Configure::read('Users.Key.Session.social')); - - return $data; + try { + return $next($request, $response); + } catch (SocialAuthenticationException $exception) { + return $this->onAuthenticationException($request, $response, $exception); } - - return false; } } From 4e68229f29ed722b273417a14fc1c5af92190eb0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 2 Nov 2018 18:32:53 -0300 Subject: [PATCH 105/685] removed unused trait --- src/Middleware/SocialEmailMiddleware.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Middleware/SocialEmailMiddleware.php b/src/Middleware/SocialEmailMiddleware.php index 0076353bb..8854f5e16 100644 --- a/src/Middleware/SocialEmailMiddleware.php +++ b/src/Middleware/SocialEmailMiddleware.php @@ -2,7 +2,6 @@ namespace CakeDC\Users\Middleware; -use CakeDC\Users\Controller\Traits\ReCaptchaTrait; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequest; @@ -11,8 +10,6 @@ class SocialEmailMiddleware extends SocialAuthMiddleware { - use ReCaptchaTrait; - /** * Complete social auth with user without social e-mail * From c3f4d0ba830595e9acacd8792400c333e82c1685 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 2 Nov 2018 18:34:32 -0300 Subject: [PATCH 106/685] removed unused imports --- src/Middleware/SocialAuthMiddleware.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index e16ec7867..1689b8805 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -2,22 +2,16 @@ namespace CakeDC\Users\Middleware; -use Cake\Routing\Router; use CakeDC\Users\Authenticator\SocialAuthenticator; -use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\SocialAuthenticationException; -use CakeDC\Users\Exception\UserNotActiveException; -use CakeDC\Users\Plugin; -use CakeDC\Users\Social\Locator\DatabaseLocator; -use CakeDC\Users\Social\MapUser; use CakeDC\Users\Social\Service\ServiceFactory; use Cake\Core\Configure; use Cake\Core\InstanceConfigTrait; -use Cake\Datasource\Exception\RecordNotFoundException; use Cake\Event\EventDispatcherTrait; use Cake\Http\ServerRequest; use Cake\Log\LogTrait; +use Cake\Routing\Router; use Psr\Http\Message\ResponseInterface; class SocialAuthMiddleware From 0943d13429abead060c126e6e3101459eb071de0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 3 Nov 2018 15:27:28 -0300 Subject: [PATCH 107/685] minor refactor on social auth --- src/Middleware/SocialAuthMiddleware.php | 23 ++++++++++++---- src/Middleware/SocialEmailMiddleware.php | 26 +++---------------- .../Middleware/SocialEmailMiddlewareTest.php | 9 +++---- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 1689b8805..f8afc9017 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -66,11 +66,7 @@ public function __invoke(ServerRequest $request, ResponseInterface $response, $n } $request = $request->withAttribute(SocialAuthenticator::SOCIAL_SERVICE_ATTRIBUTE, $service); - try { - return $next($request, $response); - } catch (SocialAuthenticationException $exception) { - return $this->onAuthenticationException($request, $response, $exception); - } + return $this->goNext($request, $response, $next); } /** @@ -134,4 +130,21 @@ protected function responseWithActionLocation(ResponseInterface $response, $acti return $response->withLocation($url); } + + /** + * Go to next handling SocialAuthenticationException + * + * @param ServerRequest $request The request + * @param ResponseInterface $response The response + * @param callable $next next middleware + * @return ResponseInterface + */ + protected function goNext(ServerRequest $request, ResponseInterface $response, $next) + { + try { + return $next($request, $response); + } catch (SocialAuthenticationException $exception) { + return $this->onAuthenticationException($request, $response, $exception); + } + } } diff --git a/src/Middleware/SocialEmailMiddleware.php b/src/Middleware/SocialEmailMiddleware.php index 8854f5e16..76f109bfd 100644 --- a/src/Middleware/SocialEmailMiddleware.php +++ b/src/Middleware/SocialEmailMiddleware.php @@ -5,7 +5,6 @@ use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequest; -use CakeDC\Users\Exception\SocialAuthenticationException; use Psr\Http\Message\ResponseInterface; class SocialEmailMiddleware extends SocialAuthMiddleware @@ -20,34 +19,17 @@ class SocialEmailMiddleware extends SocialAuthMiddleware */ public function __invoke(ServerRequest $request, ResponseInterface $response, $next) { - if ($request->getAttribute('identity')) { - $request->getSession()->delete(Configure::read('Users.Key.Session.social')); - } $action = $request->getParam('action'); if ($action !== 'socialEmail' || $request->getParam('plugin') !== 'CakeDC/Users') { + $request->getSession()->delete(Configure::read('Users.Key.Session.social')); + return $next($request, $response); } - return $this->handleAction($request, $response, $next); - } - - /** - * Handle social email step post. - * - * @param int $request authentication result - * @param \Psr\Http\Message\ServerRequestInterface $response The request. - * @param callable $next The response. - * @return \Psr\Http\Message\ResponseInterface A response - */ - private function handleAction(ServerRequest $request, ResponseInterface $response, $next) - { if (!$request->getSession()->check(Configure::read('Users.Key.Session.social'))) { throw new NotFoundException(); } - try { - return $next($request, $response); - } catch (SocialAuthenticationException $exception) { - return $this->onAuthenticationException($request, $response, $exception); - } + + return $this->goNext($request, $response, $next); } } diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index debc5391d..9fb6c28b3 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -187,7 +187,7 @@ public function testWithoutUser() * * @return void */ - public function testSuccessfullyAuthenticated() + public function testWithUser() { $Token = new \League\OAuth2\Client\Token\AccessToken([ 'access_token' => 'test-token', @@ -258,11 +258,8 @@ public function testSuccessfullyAuthenticated() $this->assertTrue(is_array($result)); $this->assertEquals(200, $result['response']->getStatusCode()); - $this->assertEquals(SocialEmailMiddleware::AUTH_SUCCESS, $result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS)); - $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); - $this->assertNotEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)['id']); - $this->assertInstanceOf(User::class, $this->Request->getSession()->read('Auth')); - $this->assertTrue($this->Request->getSession()->read('Users.successSocialLogin')); + $actual = $this->Request->getSession()->read(Configure::read('Users.Key.Session.social')); + $this->assertSame($user, $actual); } /** From 3a6a72345fc182e88e928bdb2436e01b44114d0b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 3 Nov 2018 16:14:15 -0300 Subject: [PATCH 108/685] authentication service with failures list --- src/Authentication/AuthenticationService.php | 20 +++++ src/Authentication/Failure.php | 61 ++++++++++++++ src/Authentication/FailureInterface.php | 31 ++++++++ .../AuthenticationServiceTest.php | 79 +++++++++++++++++++ .../Controller/Traits/BaseTraitTest.php | 1 - 5 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 src/Authentication/Failure.php create mode 100644 src/Authentication/FailureInterface.php diff --git a/src/Authentication/AuthenticationService.php b/src/Authentication/AuthenticationService.php index 72f29555c..38ce7517f 100644 --- a/src/Authentication/AuthenticationService.php +++ b/src/Authentication/AuthenticationService.php @@ -16,6 +16,13 @@ class AuthenticationService extends BaseService const NEED_GOOGLE_VERIFY = 'NEED_GOOGLE_VERIFY'; const GOOGLE_VERIFY_SESSION_KEY = 'temporarySession'; + + /** + * All failures authenticators + * + * @var Failure[] + */ + protected $failures = []; /** * Proceed to google verify action after a valid result result * @@ -51,6 +58,7 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface $googleVerify = Configure::read('Users.GoogleAuthenticator.login'); + $this->failures = []; $result = null; foreach ($this->authenticators() as $authenticator) { $result = $authenticator->authenticate($request, $response); @@ -74,6 +82,8 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface 'request' => $request, 'response' => $response ]; + } else { + $this->failures[] = new Failure($authenticator, $result); } if (!$result->isValid() && $authenticator instanceof StatelessInterface) { @@ -90,4 +100,14 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface 'response' => $response ]; } + + /** + * Get list the list of failures processed + * + * @return Failure[] + */ + public function getFailures() + { + return $this->failures; + } } diff --git a/src/Authentication/Failure.php b/src/Authentication/Failure.php new file mode 100644 index 000000000..40c5108da --- /dev/null +++ b/src/Authentication/Failure.php @@ -0,0 +1,61 @@ +authenticator = $authenticator; + $this->result = $result; + } + + /** + * Returns failed authenticator. + * + * @return \Authentication\Authenticator\AuthenticatorInterface + */ + public function getAuthenticator() + { + return $this->authenticator; + } + + /** + * Returns failed result. + * + * @return \Authentication\Authenticator\ResultInterface + */ + public function getResult() + { + return $this->result; + } +} diff --git a/src/Authentication/FailureInterface.php b/src/Authentication/FailureInterface.php new file mode 100644 index 000000000..d4a80c3ca --- /dev/null +++ b/src/Authentication/FailureInterface.php @@ -0,0 +1,31 @@ +get('CakeDC/Users.Users'); + $entity = $Table->get('00000000-0000-0000-0000-000000000001'); + $entity->password = 'password'; + $this->assertTrue((bool)$Table->save($entity)); + $request = ServerRequestFactory::fromGlobals( + ['REQUEST_URI' => '/testpath'], + [], + ['username' => 'user-not-found', 'password' => 'password'] + ); + $response = new Response(); + + $service = new AuthenticationService([ + 'identifiers' => [ + 'Authentication.Password' + ], + 'authenticators' => [ + 'Authentication.Session', + 'CakeDC/Users.Form' + ] + ]); + + $result = $service->authenticate($request, $response); + $this->assertInstanceOf(Result::class, $result['result']); + $this->assertInstanceOf(ServerRequestInterface::class, $result['request']); + $this->assertInstanceOf(ResponseInterface::class, $result['response']); + $this->assertFalse($result['result']->isValid()); + $result = $service->getAuthenticationProvider(); + $this->assertNull($result); + $this->assertNull( + $request->getAttribute('session')->read('Auth') + ); + $this->assertEmpty($response->getHeaderLine('Location')); + $this->assertNull($response->getStatusCode()); + + $sessionFailure = new Failure( + $service->authenticators()->get('Session'), + new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) + ); + $formFailure = new Failure( + $service->authenticators()->get('Form'), + new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND, [ + 'Password' => [] + ]) + ); + $expected = [$sessionFailure, $formFailure]; + $actual = $service->getFailures(); + $this->assertEquals($expected, $actual); + } + /** * testAuthenticate * @@ -67,6 +124,14 @@ public function testAuthenticate() ); $this->assertEmpty($response->getHeaderLine('Location')); $this->assertNull($response->getStatusCode()); + + $sessionFailure = new Failure( + $service->authenticators()->get('Session'), + new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) + ); + $expected = [$sessionFailure]; + $actual = $service->getFailures(); + $this->assertEquals($expected, $actual); } /** @@ -113,6 +178,13 @@ public function testAuthenticateShouldDoGoogleVerifyEnabled() 'user-1', $request->getAttribute('session')->read('temporarySession.username') ); + $sessionFailure = new Failure( + $service->authenticators()->get('Session'), + new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) + ); + $expected = [$sessionFailure]; + $actual = $service->getFailures(); + $this->assertEquals($expected, $actual); } /** @@ -164,5 +236,12 @@ public function testAuthenticateShouldDoGoogleVerifyDisabled() ); $this->assertEmpty($response->getHeaderLine('Location')); $this->assertNull($response->getStatusCode()); + $sessionFailure = new Failure( + $service->authenticators()->get('Session'), + new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) + ); + $expected = [$sessionFailure]; + $actual = $service->getFailures(); + $this->assertEquals($expected, $actual); } } diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 8482d833f..a1d5a417f 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -233,7 +233,6 @@ protected function _mockAuthentication($user = null) 'logoutRedirect' => $this->logoutRedirect, 'loginAction' => $this->loginAction ]); - ; } /** From 7d47aa3ffbc6e3b6daabec0007635bb4d19f8cf9 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 3 Nov 2018 19:40:34 -0300 Subject: [PATCH 109/685] login actions working with authentication service an failures list --- config/users.php | 23 ++ src/Controller/Component/LoginComponent.php | 123 ++++++ src/Controller/Traits/LoginTrait.php | 128 +------ src/Controller/Traits/SocialTrait.php | 21 +- .../Controller/Traits/BaseTraitTest.php | 10 +- .../Controller/Traits/LoginTraitTest.php | 359 ++++++++++++++---- .../Controller/Traits/SocialTraitTest.php | 142 +++---- 7 files changed, 528 insertions(+), 278 deletions(-) create mode 100644 src/Controller/Component/LoginComponent.php diff --git a/config/users.php b/config/users.php index 20b80923a..99157de1f 100644 --- a/config/users.php +++ b/config/users.php @@ -213,6 +213,29 @@ 'controller' => 'Users', 'action' => 'login', ] + ], + 'SocialLoginFailure' => [ + 'component' => 'CakeDC/Users.Login', + 'defaultMessage' => __d('CakeDC/Users', 'Could not proceed with social account. Please try again'), + 'messages' => [ + 'FAILURE_USER_NOT_ACTIVE' => __d( + 'CakeDC/Users', + 'Your user has not been validated yet. Please check your inbox for instructions' + ), + 'FAILURE_ACCOUNT_NOT_ACTIVE' => __d( + 'CakeDC/Users', + 'Your social account has not been validated yet. Please check your inbox for instructions' + ) + ], + 'targetAuthenticator' => 'CakeDC\Users\Authenticator\SocialAuthenticator' + ], + 'FormLoginFailure' => [ + 'component' => 'CakeDC/Users.Login', + 'defaultMessage' => __d('CakeDC/Users', 'Username or password is incorrect'), + 'messages' => [ + 'FAILURE_INVALID_RECAPTCHA' => __d('CakeDC/Users', 'Invalid reCaptcha'), + ], + 'targetAuthenticator' => 'CakeDC\Users\Authenticator\FormAuthenticator' ] ], 'SocialAuthMiddleware' => [ diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php new file mode 100644 index 000000000..f6bd413fe --- /dev/null +++ b/src/Controller/Component/LoginComponent.php @@ -0,0 +1,123 @@ + null, + 'messages' => [], + 'targetAuthenticator' => null, + ]; + + /** + * Handle login, if success redirect to 'AuthenticationComponent.loginRedirect' or show error + * + * @param bool $failureOnlyPost should handle failure only on post request + * @param bool $redirectFailure should redirect on failure? + * @return \Cake\Http\Response|null + */ + public function handleLogin($errorOnlyPost, $redirectFailure) + { + $request = $this->getController()->getRequest(); + $result = $request->getAttribute('authentication')->getResult(); + if ($result->isValid()) { + $user = $request->getAttribute('identity')->getOriginalData(); + + return $this->afterIdentifyUser($user); + } + if ($request->is('post') || $errorOnlyPost === false) { + return $this->handleFailure($redirectFailure); + } + } + + /** + * Handle login failure + * + * @param boolean $redirect should redirect? + * + * @return \Cake\Http\Response|null + */ + public function handleFailure($redirect = true) + { + $controller = $this->getController(); + $request = $controller->getRequest(); + + $service = $request->getAttribute('authentication'); + $result = $this->getTargetAuthenticatorResult($service); + $controller->Flash->error($this->getErrorMessage($result), 'default', [], 'auth'); + + if (!$redirect) { + return null; + } + + return $controller->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + } + + /** + * Get the target authenticator result for current login action + * + * @param AuthenticationService $service authentication service. + * @return ResultInterface|null + */ + public function getTargetAuthenticatorResult(AuthenticationService $service) + { + $target = $this->getConfig('targetAuthenticator'); + $failures = $service->getFailures(); + foreach ($failures as $failure) { + if ($failure->getAuthenticator() instanceof $target) { + return $failure->getResult(); + } + } + + return null; + } + + /** + * Get the error message for result status + * + * @param ResultInterface|null $result Result object; + * @return string + */ + public function getErrorMessage(ResultInterface $result = null) + { + $messagesMap = $this->getConfig('messages'); + + if ($result === null || !isset($messagesMap[$result->getStatus()])) { + return $this->getConfig('defaultMessage'); + } + + return $messagesMap[$result->getStatus()]; + } + + /** + * Determine redirect url after user identified + * + * @param array $user user data after identified + * @return \Cake\Http\Response + */ + protected function afterIdentifyUser($user) + { + $event = $this->getController()->dispatchEvent(Plugin::EVENT_AFTER_LOGIN, ['user' => $user]); + if (is_array($event->result)) { + return $this->getController()->redirect($event->result); + } + + return $this->getController()->redirect( + $this->getController()->Authentication->getConfig('loginRedirect') + ); + } +} diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 0d6b23da5..d5f7ddde7 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -15,6 +15,7 @@ use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Authenticator\AuthenticatorFeedbackInterface; use CakeDC\Users\Authenticator\FormAuthenticator; +use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Plugin; use Cake\Core\Configure; @@ -30,50 +31,6 @@ trait LoginTrait { use CustomUsersTableTrait; - /** - * @param int $error auth error - * @param mixed $data data - * @param bool|false $flash flash - * @return mixed - */ - public function failedSocialLogin($error, $data, $flash = false) - { - $msg = __d('CakeDC/Users', 'Issues trying to log in with your social account'); - - switch ($error) { - case SocialAuthMiddleware::AUTH_ERROR_MISSING_EMAIL: - if ($flash) { - $this->Flash->success(__d('CakeDC/Users', 'Please enter your email'), ['clear' => true]); - } - $this->request->getSession()->write(Configure::read('Users.Key.Session.social'), $data); - - return $this->redirect([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialEmail' - ]); - case SocialAuthMiddleware::AUTH_ERROR_USER_NOT_ACTIVE: - $msg = __d( - 'CakeDC/Users', - 'Your user has not been validated yet. Please check your inbox for instructions' - ); - break; - case SocialAuthMiddleware::AUTH_ERROR_ACCOUNT_NOT_ACTIVE: - $msg = __d( - 'CakeDC/Users', - 'Your social account has not been validated yet. Please check your inbox for instructions' - ); - break; - } - - if ($flash) { - $this->request->getSession()->delete(Configure::read('Users.Key.Session.social')); - $this->Flash->success($msg, ['clear' => true]); - } - - return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); - } - /** * Social login * @@ -82,21 +39,13 @@ public function failedSocialLogin($error, $data, $flash = false) */ public function socialLogin() { - $status = $this->request->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS); - if ($status === SocialAuthMiddleware::AUTH_SUCCESS) { - $user = $this->request->getAttribute('identity')->getOriginalData(); - - return $this->_afterIdentifyUser($user); - } - $socialProvider = $this->request->getParam('provider'); - - if (empty($socialProvider)) { - throw new NotFoundException(); - } + $config = Configure::read('Auth.SocialLoginFailure'); + /** + * @var \CakeDC\Users\Controller\Component\LoginComponent $Login + */ + $Login = $this->loadComponent($config['component'], $config); - $data = $this->request->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA); - - return $this->failedSocialLogin($status, $data); + return $Login->handleLogin(false, true); } /** @@ -107,64 +56,13 @@ public function socialLogin() public function login() { $this->request->getSession()->delete(AuthenticationService::GOOGLE_VERIFY_SESSION_KEY); - $result = $this->request->getAttribute('authentication')->getResult(); - - if ($result->isValid()) { - $user = $this->request->getAttribute('identity')->getOriginalData(); - - return $this->_afterIdentifyUser($user); - } - - $service = $this->request->getAttribute('authentication'); - $message = $this->_getLoginErrorMessage($service); - - if (empty($message) && $this->request->is('post')) { - $message = __d('CakeDC/Users', 'Username or password is incorrect'); - } - - if ($message) { - $this->Flash->error($message, 'default', [], 'auth'); - } - } - - /** - * Get the list of login error message map by status - * - * @return array - */ - protected function _getLoginErrorMessageMap() - { - return [ - FormAuthenticator::FAILURE_INVALID_RECAPTCHA => __d('CakeDC/Users', 'Invalid reCaptcha'), - Result::FAILURE_IDENTITY_NOT_FOUND => __d('CakeDC/Users', 'Username or password is incorrect') - ]; - } - - /** - * Show the login error message based on authenticators - * - * @param AuthenticationService $service authentication service used in request - * - * @return string - */ - protected function _getLoginErrorMessage(AuthenticationService $service) - { - $message = ''; - $errorMessages = $this->_getLoginErrorMessageMap(); - foreach ($service->authenticators() as $key => $authenticator) { - if (!$authenticator instanceof AuthenticatorFeedbackInterface) { - continue; - } - - $result = $authenticator->getLastResult(); - $status = $result ? $result->getStatus() : null; - - if ($status && isset($errorMessages[$status])) { - $message = $errorMessages[$status]; - } - } + $config = Configure::read('Auth.FormLoginFailure'); + /** + * @var \CakeDC\Users\Controller\Component\LoginComponent $Login + */ + $Login = $this->loadComponent($config['component'], $config); - return $message; + return $Login->handleLogin(true, false); } /** diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 147381de4..36cc31aff 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller\Traits; +use Cake\Core\Configure; use CakeDC\Users\Middleware\SocialAuthMiddleware; use Cake\Http\Exception\NotFoundException; @@ -29,20 +30,12 @@ trait SocialTrait */ public function socialEmail() { - if ($this->request->is('post')) { - $status = $this->request->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS); - if ($status === SocialAuthMiddleware::AUTH_ERROR_INVALID_RECAPTCHA) { - $this->Flash->error(__d('CakeDC/Users', 'The reCaptcha could not be validated')); + $config = Configure::read('Auth.SocialLoginFailure'); + /** + * @var \CakeDC\Users\Controller\Component\LoginComponent $Login + */ + $Login = $this->loadComponent($config['component'], $config); - return; - } - - $result = $this->request->getAttribute('authentication')->getResult(); - if ($result->isValid()) { - $user = $this->request->getAttribute('identity')->getOriginalData(); - - return $this->_afterIdentifyUser($user); - } - } + return $Login->handleLogin(true, false); } } diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index a1d5a417f..2469d503e 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -194,9 +194,10 @@ protected function _mockAuthLoggedIn($user = []) * Mock the Authentication service * * @param array $user + * @param array $failures * @return void */ - protected function _mockAuthentication($user = null) + protected function _mockAuthentication($user = null, $failures = []) { $config = [ 'identifiers' => [ @@ -208,7 +209,8 @@ protected function _mockAuthentication($user = null) ] ]; $authentication = $this->getMockBuilder(AuthenticationService::class)->setConstructorArgs([$config])->setMethods([ - 'getResult' + 'getResult', + 'getFailures' ])->getMock(); if ($user) { @@ -224,6 +226,10 @@ protected function _mockAuthentication($user = null) ->method('getResult') ->will($this->returnValue($result)); + $authentication->expects($this->any()) + ->method('getFailures') + ->will($this->returnValue($failures)); + $this->Trait->request = $this->Trait->request->withAttribute('authentication', $authentication); $controller = new Controller($this->Trait->request); diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 076b70d2e..0fd83a997 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -11,6 +11,15 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; +use Authentication\Authenticator\Result; +use Authentication\Authenticator\SessionAuthenticator; +use Authentication\Identifier\IdentifierCollection; +use Cake\Controller\ComponentRegistry; +use Cake\Http\Response; +use CakeDC\Users\Authentication\Failure; +use CakeDC\Users\Authenticator\FormAuthenticator; +use CakeDC\Users\Authenticator\SocialAuthenticator; +use CakeDC\Users\Controller\Component\LoginComponent; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Middleware\SocialAuthMiddleware; use Cake\Event\Event; @@ -31,7 +40,7 @@ public function setUp() parent::setUp(); $request = new ServerRequest(); $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\LoginTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set']) + ->setMethods(['dispatchEvent', 'redirect', 'set', 'loadComponent', 'getRequest']) ->getMockForTrait(); $this->Trait->Auth = $this->getMockBuilder('Cake\Controller\Component\AuthComponent') @@ -59,6 +68,15 @@ public function tearDown() */ public function testLoginHappy() { + $identifiers = new IdentifierCollection(); + $SessionAuth = new SessionAuthenticator($identifiers); + + $sessionFailure = new Failure( + $SessionAuth, + new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) + ); + $failures = [$sessionFailure]; + $this->_mockDispatchEvent(new Event('event')); $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is']) @@ -67,20 +85,46 @@ public function testLoginHappy() ->method('is') ->with('post') ->will($this->returnValue(true)); - $this->_mockAuthentication([ - 'id' => 1 - ]); - $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['error']) - ->disableOriginalConstructor() - ->getMock(); + + $this->_mockFlash(); + $this->_mockAuthentication(['id' => 1], $failures); $this->Trait->Flash->expects($this->never()) ->method('error'); - $this->Trait->expects($this->once()) ->method('redirect') - ->with($this->successLoginRedirect); - $this->Trait->login(); + ->with($this->successLoginRedirect) + ->will($this->returnValue(new Response())); + $this->Trait->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($this->Trait->request)); + + $registry = new ComponentRegistry(); + $config = [ + 'component' => 'CakeDC/Users.Login', + 'defaultMessage' => __d('CakeDC/Users', 'Username or password is incorrect'), + 'messages' => [ + FormAuthenticator::FAILURE_INVALID_RECAPTCHA => __d('CakeDC/Users', 'Invalid reCaptcha') + ], + 'targetAuthenticator' => FormAuthenticator::class + ]; + $Login = $this->getMockBuilder(LoginComponent::class) + ->setMethods(['getController']) + ->setConstructorArgs([$registry, $config]) + ->getMock(); + + $Login->expects($this->any()) + ->method('getController') + ->will($this->returnValue($this->Trait)); + $this->Trait->expects($this->any()) + ->method('loadComponent') + ->with( + $this->equalTo('CakeDC/Users.Login'), + $this->equalTo($config) + ) + ->will($this->returnValue($Login)); + + $result = $this->Trait->login(); + $this->assertInstanceOf(Response::class, $result); } /** @@ -110,6 +154,35 @@ public function testLoginGet() ->method('redirect'); $this->_mockAuthentication(); + + $registry = new ComponentRegistry(); + $config = [ + 'component' => 'CakeDC/Users.Login', + 'defaultMessage' => __d('CakeDC/Users', 'Username or password is incorrect'), + 'messages' => [ + FormAuthenticator::FAILURE_INVALID_RECAPTCHA => __d('CakeDC/Users', 'Invalid reCaptcha') + ], + 'targetAuthenticator' => FormAuthenticator::class + ]; + $Login = $this->getMockBuilder(LoginComponent::class) + ->setMethods(['getController']) + ->setConstructorArgs([$registry, $config]) + ->getMock(); + + $Login->expects($this->any()) + ->method('getController') + ->will($this->returnValue($this->Trait)); + $this->Trait->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($this->Trait->request)); + $this->Trait->expects($this->any()) + ->method('loadComponent') + ->with( + $this->equalTo('CakeDC/Users.Login'), + $this->equalTo($config) + ) + ->will($this->returnValue($Login)); + $this->Trait->login(); } @@ -142,98 +215,230 @@ public function testLogout() } /** - * test - * - * @return void + * Data provider for testLogin */ - public function testFailedSocialLoginMissingEmail() + public function dataProviderLogin() { - $data = [ - 'id' => 11111, - 'username' => 'user-1' + $socialLoginConfig = [ + 'component' => 'CakeDC/Users.Login', + 'defaultMessage' => __d('CakeDC/Users', 'Could not proceed with social account. Please try again'), + 'messages' => [ + SocialAuthenticator::FAILURE_USER_NOT_ACTIVE => __d( + 'CakeDC/Users', + 'Your user has not been validated yet. Please check your inbox for instructions' + ), + SocialAuthenticator::FAILURE_ACCOUNT_NOT_ACTIVE => __d( + 'CakeDC/Users', + 'Your social account has not been validated yet. Please check your inbox for instructions' + ) + ], + 'targetAuthenticator' => SocialAuthenticator::class + ]; + $loginConfig = [ + 'component' => 'CakeDC/Users.Login', + 'defaultMessage' => __d('CakeDC/Users', 'Username or password is incorrect'), + 'messages' => [ + FormAuthenticator::FAILURE_INVALID_RECAPTCHA => __d('CakeDC/Users', 'Invalid reCaptcha'), + ], + 'targetAuthenticator' => FormAuthenticator::class + ]; + return [ + [ + SocialAuthenticator::class, + SocialAuthenticator::FAILURE_USER_NOT_ACTIVE, + 'Your user has not been validated yet. Please check your inbox for instructions', + 'socialLogin', + $socialLoginConfig + ], + [ + SocialAuthenticator::class, + SocialAuthenticator::FAILURE_ACCOUNT_NOT_ACTIVE, + 'Your social account has not been validated yet. Please check your inbox for instructions', + 'socialLogin', + $socialLoginConfig + ], + [ + SocialAuthenticator::class, + Result::FAILURE_IDENTITY_NOT_FOUND, + 'Could not proceed with social account. Please try again', + 'socialLogin', + $socialLoginConfig + ], + [ + FormAuthenticator::class, + Result::FAILURE_IDENTITY_NOT_FOUND, + 'Username or password is incorrect', + 'login', + $loginConfig + ], + [ + FormAuthenticator::class, + FormAuthenticator::FAILURE_INVALID_RECAPTCHA, + 'Invalid reCaptcha', + 'login', + $loginConfig + ] ]; - $this->_mockFlash(); - $this->_mockAuthentication(); - $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(SocialAuthMiddleware::AUTH_ERROR_MISSING_EMAIL, $data, true); } - /** - * test + * test socialLogin/login failure * + * @dataProvider dataProviderLogin * @return void */ - public function testFailedSocialUserNotActive() + public function testLogin($AuthClass, $resultStatus, $message, $method, $failureConfig) { - $data = [ - 'id' => 111111, - 'username' => 'user-1' - ]; + $identifiers = new IdentifierCollection([ + 'CakeDC/Users.Social' + ]); + $FormAuth = new FormAuthenticator($identifiers); + $SessionAuth = new SessionAuthenticator($identifiers); + $SocialAuth = new $AuthClass($identifiers); + + $sessionFailure = new Failure( + $SessionAuth, + new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) + ); + $formFailure = new Failure( + $FormAuth, + new Result(null, $resultStatus, [ + 'Password' => [] + ]) + ); + $socialFailure = new Failure( + $SocialAuth, + new Result(null, $resultStatus) + ); + $failures = [$sessionFailure, $formFailure, $socialFailure]; + + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->setMethods(['is']) + ->getMock(); + $this->Trait->request->expects($this->any()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); $this->_mockFlash(); - $this->_mockAuthentication(); + $this->_mockAuthentication(null, $failures); $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Your user has not been validated yet. Please check your inbox for instructions'); + ->method('error') + ->with($message); + $this->Trait->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($this->Trait->request)); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $registry = new ComponentRegistry(); + $Login = $this->getMockBuilder(LoginComponent::class) + ->setMethods(['getController']) + ->setConstructorArgs([$registry, $failureConfig]) + ->getMock(); - $this->Trait->failedSocialLogin(SocialAuthMiddleware::AUTH_ERROR_USER_NOT_ACTIVE, $data, true); + $Login->expects($this->any()) + ->method('getController') + ->will($this->returnValue($this->Trait)); + $this->Trait->expects($this->any()) + ->method('loadComponent') + ->with( + $this->equalTo('CakeDC/Users.Login'), + $this->equalTo($failureConfig) + ) + ->will($this->returnValue($Login)); + + if ($method === 'login') { + $this->Trait->expects($this->never()) + ->method('redirect'); + $result = $this->Trait->$method(); + $this->assertNull($result); + } else { + $this->Trait->expects($this->once()) + ->method('redirect') + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']) + ->will($this->returnValue(new Response())); + $result = $this->Trait->$method(); + $this->assertInstanceOf(Response::class, $result); + } } /** - * test + * test socialLogin success * * @return void */ - public function testFailedSocialUserAccountNotActive() + public function testSocialLoginSuccess() { - $data = [ - 'id' => 111111, - 'username' => 'user-1' - ]; - $this->_mockFlash(); - $this->_mockAuthentication(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Your social account has not been validated yet. Please check your inbox for instructions'); + $identifiers = new IdentifierCollection([ + 'CakeDC/Users.Social' + ]); + $FormAuth = new FormAuthenticator($identifiers); + $SessionAuth = new SessionAuthenticator($identifiers); - $this->Trait->expects($this->once()) - ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + $sessionFailure = new Failure( + $SessionAuth, + new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) + ); + $formFailure = new Failure( + $FormAuth, + new Result(null, Result::FAILURE_CREDENTIALS_MISSING, [ + 'Password' => [] + ]) + ); + $failures = [$sessionFailure, $formFailure]; - $this->Trait->failedSocialLogin(SocialAuthMiddleware::AUTH_ERROR_ACCOUNT_NOT_ACTIVE, $data, true); - } + $this->_mockDispatchEvent(new Event('event')); + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->setMethods(['is']) + ->getMock(); + $this->Trait->request->expects($this->any()) + ->method('is') + ->with('post') + ->will($this->returnValue(true)); - /** - * test - * - * @return void - */ - public function testFailedSocialUserAccount() - { - $data = [ - 'id' => 111111, - 'username' => 'user-1' - ]; $this->_mockFlash(); - $this->_mockAuthentication(); - $this->Trait->Flash->expects($this->once()) - ->method('success') - ->with('Issues trying to log in with your social account'); - + $this->_mockAuthentication(['id' => 1], $failures); + $this->Trait->Flash->expects($this->never()) + ->method('error'); $this->Trait->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + ->with($this->successLoginRedirect) + ->will($this->returnValue(new Response())); + $this->Trait->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($this->Trait->request)); + + $registry = new ComponentRegistry(); + $config = [ + 'component' => 'CakeDC/Users.Login', + 'defaultMessage' => __d('CakeDC/Users', 'Could not proceed with social account. Please try again'), + 'messages' => [ + SocialAuthenticator::FAILURE_USER_NOT_ACTIVE => __d( + 'CakeDC/Users', + 'Your user has not been validated yet. Please check your inbox for instructions' + ), + SocialAuthenticator::FAILURE_ACCOUNT_NOT_ACTIVE => __d( + 'CakeDC/Users', + 'Your social account has not been validated yet. Please check your inbox for instructions' + ) + ], + 'targetAuthenticator' => SocialAuthenticator::class + ]; + $Login = $this->getMockBuilder(LoginComponent::class) + ->setMethods(['getController']) + ->setConstructorArgs([$registry, $config]) + ->getMock(); + + $Login->expects($this->any()) + ->method('getController') + ->will($this->returnValue($this->Trait)); + $this->Trait->expects($this->any()) + ->method('loadComponent') + ->with( + $this->equalTo('CakeDC/Users.Login'), + $this->equalTo($config) + ) + ->will($this->returnValue($Login)); - $this->Trait->failedSocialLogin(null, $data, true); + $result = $this->Trait->socialLogin(); + $this->assertInstanceOf(Response::class, $result); } } diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index 0d2fab13b..faf3eb675 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -11,6 +11,15 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; +use Authentication\Authenticator\Result; +use Authentication\Authenticator\SessionAuthenticator; +use Authentication\Identifier\IdentifierCollection; +use Cake\Controller\ComponentRegistry; +use Cake\Event\Event; +use CakeDC\Users\Authentication\Failure; +use CakeDC\Users\Authenticator\FormAuthenticator; +use CakeDC\Users\Authenticator\SocialAuthenticator; +use CakeDC\Users\Controller\Component\LoginComponent; use CakeDC\Users\Middleware\SocialAuthMiddleware; use Cake\Http\Response; use Cake\Http\ServerRequest; @@ -25,12 +34,12 @@ class SocialTraitTest extends BaseTraitTest public function setUp() { $this->traitClassName = 'CakeDC\Users\Controller\Traits\SocialTrait'; - $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set', '_afterIdentifyUser']; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; parent::setUp(); $request = new ServerRequest(); $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\SocialTrait') - ->setMethods(['dispatchEvent', 'redirect', 'set', '_afterIdentifyUser']) + ->setMethods(['dispatchEvent', 'redirect', 'set', 'loadComponent', 'getRequest']) ->getMockForTrait(); $this->Trait->request = $request; @@ -47,38 +56,31 @@ public function tearDown() } /** - * Test socialEmail get + * test socialLogin success * + * @return void */ - public function testSocialEmailHappyGet() + public function testSocialEmailSuccess() { - $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') - ->setMethods(['is']) - ->getMock(); - $this->Trait->request->expects($this->any()) - ->method('is') - ->with('post') - ->will($this->returnValue(false)); - $this->_mockAuthentication(); - $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['error']) - ->disableOriginalConstructor() - ->getMock(); - $this->Trait->Flash->expects($this->never()) - ->method('error'); - $this->Trait->expects($this->never()) - ->method('_afterIdentifyUser'); - $this->Trait->expects($this->never()) - ->method('redirect'); + $identifiers = new IdentifierCollection([ + 'CakeDC/Users.Social' + ]); + $FormAuth = new FormAuthenticator($identifiers); + $SessionAuth = new SessionAuthenticator($identifiers); - $this->Trait->socialEmail(); - } - /** - * Test socialEmail - * - */ - public function testSocialEmailHappy() - { + $sessionFailure = new Failure( + $SessionAuth, + new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) + ); + $formFailure = new Failure( + $FormAuth, + new Result(null, Result::FAILURE_CREDENTIALS_MISSING, [ + 'Password' => [] + ]) + ); + $failures = [$sessionFailure, $formFailure]; + + $this->_mockDispatchEvent(new Event('event')); $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is']) ->getMock(); @@ -86,52 +88,52 @@ public function testSocialEmailHappy() ->method('is') ->with('post') ->will($this->returnValue(true)); - $this->_mockAuthentication([ - 'id' => 1 - ]); - $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['error']) - ->disableOriginalConstructor() - ->getMock(); + + $this->_mockFlash(); + $this->_mockAuthentication(['id' => 1], $failures); $this->Trait->Flash->expects($this->never()) ->method('error'); - $user = $this->Trait->request->getAttribute('identity')->getOriginalData(); - $response = new Response(); - $response->withStringBody("testSocialEmailHappy"); $this->Trait->expects($this->once()) - ->method('_afterIdentifyUser') - ->with($user) - ->will($this->returnValue($response)); - - $this->assertSame($response, $this->Trait->socialEmail()); - } + ->method('redirect') + ->with($this->successLoginRedirect) + ->will($this->returnValue(new Response())); + $this->Trait->expects($this->any()) + ->method('getRequest') + ->will($this->returnValue($this->Trait->request)); - /** - * Test socialEmail - * - */ - public function testSocialEmailInvalidRecaptcha() - { - $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') - ->setMethods(['is']) - ->getMock(); - $this->Trait->request->expects($this->any()) - ->method('is') - ->with('post') - ->will($this->returnValue(true)); - $this->_mockAuthentication(); - $this->Trait->request = $this->Trait->request->withAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS, SocialAuthMiddleware::AUTH_ERROR_INVALID_RECAPTCHA); - $this->Trait->Flash = $this->getMockBuilder('Cake\Controller\Component\FlashComponent') - ->setMethods(['error']) - ->disableOriginalConstructor() + $registry = new ComponentRegistry(); + $config = [ + 'component' => 'CakeDC/Users.Login', + 'defaultMessage' => __d('CakeDC/Users', 'Could not proceed with social account. Please try again'), + 'messages' => [ + SocialAuthenticator::FAILURE_USER_NOT_ACTIVE => __d( + 'CakeDC/Users', + 'Your user has not been validated yet. Please check your inbox for instructions' + ), + SocialAuthenticator::FAILURE_ACCOUNT_NOT_ACTIVE => __d( + 'CakeDC/Users', + 'Your social account has not been validated yet. Please check your inbox for instructions' + ) + ], + 'targetAuthenticator' => SocialAuthenticator::class + ]; + $Login = $this->getMockBuilder(LoginComponent::class) + ->setMethods(['getController']) + ->setConstructorArgs([$registry, $config]) ->getMock(); - $this->Trait->Flash->expects($this->once()) - ->method('error') - ->with('The reCaptcha could not be validated'); - $this->Trait->expects($this->never()) - ->method('_afterIdentifyUser'); + $Login->expects($this->any()) + ->method('getController') + ->will($this->returnValue($this->Trait)); + $this->Trait->expects($this->any()) + ->method('loadComponent') + ->with( + $this->equalTo('CakeDC/Users.Login'), + $this->equalTo($config) + ) + ->will($this->returnValue($Login)); - $this->Trait->socialEmail(); + $result = $this->Trait->socialEmail(); + $this->assertInstanceOf(Response::class, $result); } } From eb57e72095af30fbd0453343b39e045e439e86ff Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 3 Nov 2018 20:09:27 -0300 Subject: [PATCH 110/685] minor cleanup --- config/users.php | 7 +++ src/Authenticator/SocialAuthenticator.php | 24 +-------- .../SocialPendingEmailAuthenticator.php | 6 +-- src/Middleware/SocialAuthMiddleware.php | 4 +- .../SocialPendingEmailAuthenticatorTest.php | 52 +------------------ 5 files changed, 13 insertions(+), 80 deletions(-) diff --git a/config/users.php b/config/users.php index 99157de1f..4e8dbf475 100644 --- a/config/users.php +++ b/config/users.php @@ -177,9 +177,16 @@ 'prefix' => false, ] ], + 'CakeDC/Users.Social' => [ + 'skipGoogleVerify' => true, + ], + 'CakeDC/Users.SocialPendingEmail' => [ + 'skipGoogleVerify' => true, + ] ], 'Identifiers' => [ 'Authentication.Password', + "CakeDC/Users.Social", 'Authentication.Token' => [ 'tokenField' => 'api_token' ] diff --git a/src/Authenticator/SocialAuthenticator.php b/src/Authenticator/SocialAuthenticator.php index 7528d6c6a..320d239ea 100644 --- a/src/Authenticator/SocialAuthenticator.php +++ b/src/Authenticator/SocialAuthenticator.php @@ -40,29 +40,7 @@ class SocialAuthenticator extends AbstractAuthenticator * * @var array */ - protected $_defaultConfig = [ - 'loginUrl' => null, - 'urlChecker' => 'Authentication.Default', - ]; - - /** - * Prepares the error object for a login URL error - * - * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. - * @return \Authentication\Authenticator\ResultInterface - */ - protected function _buildLoginUrlErrorResult($request) - { - $errors = [ - sprintf( - 'Login URL `%s` did not match `%s`.', - (string)$request->getUri(), - implode('` or `', (array)$this->getConfig('loginUrl')) - ) - ]; - - return new Result(null, Result::FAILURE_OTHER, $errors); - } + protected $_defaultConfig = []; /** * Authenticates the identity contained in a request. Will use the `config.userModel`, and `config.fields` diff --git a/src/Authenticator/SocialPendingEmailAuthenticator.php b/src/Authenticator/SocialPendingEmailAuthenticator.php index 0d4f36a43..b28b62ae6 100644 --- a/src/Authenticator/SocialPendingEmailAuthenticator.php +++ b/src/Authenticator/SocialPendingEmailAuthenticator.php @@ -87,14 +87,10 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface $rawData = $request->getSession()->read(Configure::read('Users.Key.Session.social')); $body = $request->getParsedBody(); $email = Hash::get($body, 'email'); + if (empty($rawData) || empty($email)) { return new Result(null, Result::FAILURE_CREDENTIALS_MISSING); } - $captcha = Hash::get($body, 'g-recaptcha-response'); - if (!$this->validateReCaptcha($captcha, $request->clientIp())) { - return new Result(null, self::FAILURE_INVALID_RECAPTCHA); - } - $rawData['email'] = $email; return $this->identify($rawData); diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index f8afc9017..70fac4fac 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -110,9 +110,9 @@ private function setErrorMessage(ServerRequest $request, $message) $messages = (array)$request->getSession()->read('Flash.flash'); $messages[] = [ 'key' => 'flash', - 'element' => 'error', + 'element' => 'Flash/error', 'params' => [], - $message + 'message' => $message ]; $request->getSession()->write('Flash.flash', $messages); } diff --git a/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php index 097f7fd9c..7dc4855e9 100644 --- a/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php @@ -64,7 +64,7 @@ public function testAuthenticateBaseFailed() $request = ServerRequestFactory::fromGlobals( ['REQUEST_URI' => '/users/users/social-email'], [], - ['email' => 'testAuthenticateBaseFailed@example.com', 'g-recaptcha-response' => 'BD-S2333-156465897897'] + ['email' => 'testAuthenticateBaseFailed@example.com'] ); $requestNoEmail = ServerRequestFactory::fromGlobals( ['REQUEST_URI' => '/users/users/social-email'], @@ -83,16 +83,7 @@ public function testAuthenticateBaseFailed() $this->assertInstanceOf(Result::class, $result); $this->assertEquals(Result::FAILURE_CREDENTIALS_MISSING, $result->getStatus()); - $Authenticator = $this->getMockBuilder(SocialPendingEmailAuthenticator::class)->setConstructorArgs([ - $identifiers - ])->setMethods(['validateReCaptcha'])->getMock(); - - $Authenticator->expects($this->once()) - ->method('validateReCaptcha') - ->with( - $this->equalTo('BD-S2333-156465897897') - ) - ->will($this->returnValue(true)); + $Authenticator = new SocialPendingEmailAuthenticator($identifiers); $result = $Authenticator->authenticate($request, $Response); $this->assertInstanceOf(Result::class, $result); @@ -102,45 +93,6 @@ public function testAuthenticateBaseFailed() $this->assertEquals('testAuthenticateBaseFailed@example.com', $data['email']); } - /** - * testAuthenticate - * - * @return void - */ - public function testAuthenticateInvalidRecaptcha() - { - $identifiers = new IdentifierCollection([ - 'Authentication.Password' - ]); - - $request = ServerRequestFactory::fromGlobals( - ['REQUEST_URI' => '/users/users/social-email'], - [], - ['email' => 'testAuthenticateBaseFailed@example.com', 'g-recaptcha-response' => 'BD-S2333-156465897897'] - ); - $response = new Response(); - - $Authenticator = $this->getMockBuilder(SocialPendingEmailAuthenticator::class)->setConstructorArgs([ - $identifiers - ])->setMethods(['validateReCaptcha'])->getMock(); - - $Authenticator->expects($this->once()) - ->method('validateReCaptcha') - ->with( - $this->equalTo('BD-S2333-156465897897') - ) - ->will($this->returnValue(false)); - - $user = $this->getUserData(); - Configure::write('Users.reCaptcha.login', true); - Configure::write('Users.Email.validate', false); - $request->getSession()->write(Configure::read('Users.Key.Session.social'), $user); - $result = $Authenticator->authenticate($request, $response); - $this->assertInstanceOf(Result::class, $result); - $this->assertEquals(SocialPendingEmailAuthenticator::FAILURE_INVALID_RECAPTCHA, $result->getStatus()); - $this->assertNull($result->getData()); - } - /** * Get social user data for test * From d1b2754fcefac07321682f269b6e955f5bb03952 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 3 Nov 2018 20:16:03 -0300 Subject: [PATCH 111/685] minor cleanup --- config/users.php | 4 +++- src/Identifier/SocialIdentifier.php | 1 - src/Middleware/SocialAuthMiddleware.php | 21 ------------------- .../Middleware/SocialEmailMiddlewareTest.php | 5 ----- 4 files changed, 3 insertions(+), 28 deletions(-) diff --git a/config/users.php b/config/users.php index 4e8dbf475..67691f9f0 100644 --- a/config/users.php +++ b/config/users.php @@ -186,7 +186,9 @@ ], 'Identifiers' => [ 'Authentication.Password', - "CakeDC/Users.Social", + "CakeDC/Users.Social" => [ + 'authFinder' => 'all' + ], 'Authentication.Token' => [ 'tokenField' => 'api_token' ] diff --git a/src/Identifier/SocialIdentifier.php b/src/Identifier/SocialIdentifier.php index 94fd300cd..a1873d564 100644 --- a/src/Identifier/SocialIdentifier.php +++ b/src/Identifier/SocialIdentifier.php @@ -27,7 +27,6 @@ class SocialIdentifier extends AbstractIdentifier * @var array */ protected $_defaultConfig = [ - 'resolver' => 'Authentication.Orm', 'authFinder' => 'all' ]; diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 70fac4fac..0833b138f 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -7,8 +7,6 @@ use CakeDC\Users\Exception\SocialAuthenticationException; use CakeDC\Users\Social\Service\ServiceFactory; use Cake\Core\Configure; -use Cake\Core\InstanceConfigTrait; -use Cake\Event\EventDispatcherTrait; use Cake\Http\ServerRequest; use Cake\Log\LogTrait; use Cake\Routing\Router; @@ -16,28 +14,9 @@ class SocialAuthMiddleware { - use EventDispatcherTrait; - use InstanceConfigTrait; use LogTrait; - const AUTH_ERROR_MISSING_EMAIL = 10; - const AUTH_ERROR_ACCOUNT_NOT_ACTIVE = 20; - const AUTH_ERROR_USER_NOT_ACTIVE = 30; - const AUTH_ERROR_INVALID_RECAPTCHA = 40; - const AUTH_ERROR_FIND_USER = 50; - const AUTH_SUCCESS = 100; - - const ATTRIBUTE_NAME_SOCIAL_RAW_DATA = 'socialRawData'; - const ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS = 'socialAuthStatus'; - protected $_defaultConfig = []; - protected $authStatus = 0; - protected $rawData = []; - - /** - * @var \CakeDC\Users\Social\Service\ServiceInterface - */ - protected $service; protected $params = [ 'plugin' => 'CakeDC/Users', diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index 9fb6c28b3..6c67c073a 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -146,9 +146,6 @@ public function testWithGetRquest() $result = $Middleware($this->Request, $response, $next); $this->assertTrue(is_array($result)); - - $this->assertEquals(null, $result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS)); - $this->assertEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); $this->assertEmpty($this->Request->getSession()->read('Auth')); $this->assertEmpty($this->Request->getSession()->read('Users.successSocialLogin')); } @@ -335,8 +332,6 @@ public function testWithoutEmail() $this->assertTrue(is_array($result)); $this->assertEquals(200, $result['response']->getStatusCode()); - $this->assertEquals(0, $result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_AUTH_STATUS)); - $this->assertEmpty($result['request']->getAttribute(SocialAuthMiddleware::ATTRIBUTE_NAME_SOCIAL_RAW_DATA)); $this->assertEmpty($this->Request->getSession()->read('Auth')); } From c3ea928d3194a137e01b893e3dad0645585d9534 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 3 Nov 2018 20:27:30 -0300 Subject: [PATCH 112/685] fixed logout url --- config/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index 67691f9f0..44ff5b881 100644 --- a/config/users.php +++ b/config/users.php @@ -136,7 +136,7 @@ 'logoutRedirect' => [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', - 'action' => 'logout', + 'action' => 'login', 'prefix' => false, ], 'loginRedirect' => '/', From f6cac38d6eb9980b435a4a9c3cb74ee271dc0488 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 3 Nov 2018 20:31:03 -0300 Subject: [PATCH 113/685] identifier item with array as config --- config/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index 44ff5b881..a44a331d5 100644 --- a/config/users.php +++ b/config/users.php @@ -185,7 +185,7 @@ ] ], 'Identifiers' => [ - 'Authentication.Password', + 'Authentication.Password' => [], "CakeDC/Users.Social" => [ 'authFinder' => 'all' ], From 01d24287624b1798d45277e4c67dc862c0842cb6 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 4 Nov 2018 16:38:20 -0200 Subject: [PATCH 114/685] minor refactor for social identifier credential key --- src/Authenticator/SocialAuthTrait.php | 3 ++- src/Identifier/SocialIdentifier.php | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Authenticator/SocialAuthTrait.php b/src/Authenticator/SocialAuthTrait.php index 061657325..14303078c 100644 --- a/src/Authenticator/SocialAuthTrait.php +++ b/src/Authenticator/SocialAuthTrait.php @@ -17,6 +17,7 @@ use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\SocialAuthenticationException; use CakeDC\Users\Exception\UserNotActiveException; +use CakeDC\Users\Identifier\SocialIdentifier; trait SocialAuthTrait { @@ -28,7 +29,7 @@ trait SocialAuthTrait protected function identify($rawData) { try { - $user = $this->getIdentifier()->identify(['socialAuthUser' => $rawData]); + $user = $this->getIdentifier()->identify([SocialIdentifier::CREDENTIAL_KEY => $rawData]); if (!empty($user)) { return new Result($user, Result::SUCCESS); } diff --git a/src/Identifier/SocialIdentifier.php b/src/Identifier/SocialIdentifier.php index a1873d564..3ad79a6f1 100644 --- a/src/Identifier/SocialIdentifier.php +++ b/src/Identifier/SocialIdentifier.php @@ -19,6 +19,8 @@ class SocialIdentifier extends AbstractIdentifier { use LocatorAwareTrait; + const CREDENTIAL_KEY = 'socialAuthUser'; + /** * Default configuration. * - `usersTable` name of usersTable to use: @@ -38,11 +40,11 @@ class SocialIdentifier extends AbstractIdentifier */ public function identify(array $credentials) { - if (!isset($credentials['socialAuthUser'])) { + if (!isset($credentials[self::CREDENTIAL_KEY])) { return null; } - $user = $this->createOrGetUser($credentials['socialAuthUser']); + $user = $this->createOrGetUser($credentials[self::CREDENTIAL_KEY]); if (!$user) { return null; From 7a488d791c3a1a341e6bf6cbf4198f67f95492bc Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 4 Nov 2018 16:40:13 -0200 Subject: [PATCH 115/685] removed unused method --- src/Controller/Traits/LoginTrait.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index d5f7ddde7..d21251bfb 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -65,22 +65,6 @@ public function login() return $Login->handleLogin(true, false); } - /** - * Determine redirect url after user identified - * - * @param array $user user data after identified - * @return array - */ - protected function _afterIdentifyUser($user) - { - $event = $this->dispatchEvent(Plugin::EVENT_AFTER_LOGIN, ['user' => $user]); - if (is_array($event->result)) { - return $this->redirect($event->result); - } - - return $this->redirect($this->Authentication->getConfig('loginRedirect')); - } - /** * Logout * From 8b4abf30c10279f8e85b93f2623b7c1e55063ba1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 4 Nov 2018 17:25:47 -0200 Subject: [PATCH 116/685] fixing flash message test --- tests/TestCase/Middleware/SocialAuthMiddlewareTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index ebcec49c7..244a6db5f 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -247,9 +247,9 @@ public function dataProviderSocialAuthenticationException() new MissingEmailException("Missing email"), [ 'key' => 'flash', - 'element' => 'error', + 'element' => 'Flash/error', 'params' => [], - __d('CakeDC/Users', 'Please enter your email') + 'message' => __d('CakeDC/Users', 'Please enter your email') ], '/users/users/social-email', true, @@ -258,9 +258,9 @@ public function dataProviderSocialAuthenticationException() new UnexpectedValueException("User not active"), [ 'key' => 'flash', - 'element' => 'error', + 'element' => 'Flash/error', 'params' => [], - __d('CakeDC/Users', 'Could not identify your account, please try again') + 'message' => __d('CakeDC/Users', 'Could not identify your account, please try again') ], '/login', false From daac053ed13012360348d727a03f28802d26cb1c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 4 Nov 2018 17:59:52 -0200 Subject: [PATCH 117/685] added a utility class to get/check users action --- src/Middleware/SocialAuthMiddleware.php | 14 +- src/Middleware/SocialEmailMiddleware.php | 4 +- src/Utility/UsersUrl.php | 57 ++++++++ tests/TestCase/Utility/UsersUrlTest.php | 164 +++++++++++++++++++++++ 4 files changed, 226 insertions(+), 13 deletions(-) create mode 100644 src/Utility/UsersUrl.php create mode 100644 tests/TestCase/Utility/UsersUrlTest.php diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 0833b138f..4ac5c0163 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -10,20 +10,13 @@ use Cake\Http\ServerRequest; use Cake\Log\LogTrait; use Cake\Routing\Router; +use CakeDC\Users\Utility\UsersUrl; use Psr\Http\Message\ResponseInterface; class SocialAuthMiddleware { use LogTrait; - protected $_defaultConfig = []; - - protected $params = [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin' - ]; - /** * Perform social auth * @@ -34,8 +27,7 @@ class SocialAuthMiddleware */ public function __invoke(ServerRequest $request, ResponseInterface $response, $next) { - $action = $request->getParam('action'); - if ($action !== 'socialLogin' || $request->getParam('plugin') !== 'CakeDC/Users') { + if (!(new UsersUrl())->checkActionOnRequest('socialLogin', $request)) { return $next($request, $response); } @@ -105,7 +97,7 @@ private function setErrorMessage(ServerRequest $request, $message) */ protected function responseWithActionLocation(ResponseInterface $response, $action) { - $url = Router::url(compact('action') + $this->params); + $url = Router::url((new UsersUrl())->actionUrl($action)); return $response->withLocation($url); } diff --git a/src/Middleware/SocialEmailMiddleware.php b/src/Middleware/SocialEmailMiddleware.php index 76f109bfd..3918a6741 100644 --- a/src/Middleware/SocialEmailMiddleware.php +++ b/src/Middleware/SocialEmailMiddleware.php @@ -5,6 +5,7 @@ use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequest; +use CakeDC\Users\Utility\UsersUrl; use Psr\Http\Message\ResponseInterface; class SocialEmailMiddleware extends SocialAuthMiddleware @@ -19,8 +20,7 @@ class SocialEmailMiddleware extends SocialAuthMiddleware */ public function __invoke(ServerRequest $request, ResponseInterface $response, $next) { - $action = $request->getParam('action'); - if ($action !== 'socialEmail' || $request->getParam('plugin') !== 'CakeDC/Users') { + if (!(new UsersUrl())->checkActionOnRequest('socialEmail', $request)) { $request->getSession()->delete(Configure::read('Users.Key.Session.social')); return $next($request, $response); diff --git a/src/Utility/UsersUrl.php b/src/Utility/UsersUrl.php new file mode 100644 index 000000000..ce80e7997 --- /dev/null +++ b/src/Utility/UsersUrl.php @@ -0,0 +1,57 @@ +actionUrl($action); + foreach ($url as $param => $value) { + if ($request->getParam($param) !== $value) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/tests/TestCase/Utility/UsersUrlTest.php b/tests/TestCase/Utility/UsersUrlTest.php new file mode 100644 index 000000000..feded4784 --- /dev/null +++ b/tests/TestCase/Utility/UsersUrlTest.php @@ -0,0 +1,164 @@ + false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify'], null], + ['linkSocial', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial'], null], + ['callbackLinkSocial', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'callbackLinkSocial'], null], + ['socialLogin', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin'], null], + ['login', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login'], null], + ['logout', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout'], null], + ['getUsersTable', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'getUsersTable'], null], + ['setUsersTable', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'setUsersTable'], null], + ['profile', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], null], + ['validateReCaptcha', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateReCaptcha'], null], + ['register', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'register'], null], + ['validateEmail', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail'], null], + ['changePassword', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'changePassword'], null], + ['resetPassword', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetPassword'], null], + ['requestResetPassword', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'requestResetPassword'], null], + ['resetGoogleAuthenticator', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetGoogleAuthenticator'], null], + ['validate', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validate'], null], + ['resendTokenValidation', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resendTokenValidation'], null], + ['index', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'index'], null], + ['view', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'view'], null], + ['add', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'add'], null], + ['edit', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'edit'], null], + ['delete', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'delete'], null], + ['socialEmail', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail'], null], + + ['verify', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'verify'], 'Users'], + ['linkSocial', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'linkSocial'], 'Users'], + ['callbackLinkSocial', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'callbackLinkSocial'], 'Users'], + ['socialLogin', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'socialLogin'], 'Users'], + ['login', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'login'], 'Users'], + ['logout', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'logout'], 'Users'], + ['getUsersTable', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'getUsersTable'], 'Users'], + ['setUsersTable', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'setUsersTable'], 'Users'], + ['profile', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'profile'], 'Users'], + ['validateReCaptcha', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'validateReCaptcha'], 'Users'], + ['register', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'register'], 'Users'], + ['validateEmail', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'validateEmail'], 'Users'], + ['changePassword', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'changePassword'], 'Users'], + ['resetPassword', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'resetPassword'], 'Users'], + ['requestResetPassword', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'requestResetPassword'], 'Users'], + ['resetGoogleAuthenticator', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'resetGoogleAuthenticator'], 'Users'], + ['validate', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'validate'], 'Users'], + ['resendTokenValidation', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'resendTokenValidation'], 'Users'], + ['index', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'index'], 'Users'], + ['view', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'view'], 'Users'], + ['add', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'add'], 'Users'], + ['edit', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'edit'], 'Users'], + ['delete', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'delete'], 'Users'], + ['socialEmail', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'socialEmail'], 'Users'] + ]; + } + + /** + * Test actionUrl method + * + * @dataProvider dataProviderActionUrl + * @param string $action user action. + * @param array $expected expected url + * @param string $controller controller name for users, optional + * @return void + */ + public function testActionUrl($action, $expected, $controller = null) + { + $UsersUrl = new UsersUrl(); + Configure::write('Users.controller', $controller); + $actual = $UsersUrl->actionUrl($action); + $this->assertEquals($expected, $actual); + } + + /** + * Data provider for testCheckActionOnRequest + * + * @return array + */ + public function dataProviderCheckActionOnRequest() + { + return [ + [ + 'socialLogin', + ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'provider' => 'facebook'], + null, + true + ], + [ + 'socialLogin', + ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'provider' => 'facebook'], + 'CakeDC/Users.Users', + true, + ], + [ + 'socialLogin', + ['plugin' => false, 'controller' => 'Users', 'action' => 'socialLogin', 'provider' => 'facebook'], + 'CakeDC/Users.Users', + false, + ], + [ + 'login', + ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'provider' => 'facebook'], + 'CakeDC/Users.Users', + false, + ], + [ + 'socialLogin', + ['plugin' => false, 'controller' => 'Users', 'action' => 'socialLogin', 'provider' => 'facebook'], + 'Users', + true, + ], + ]; + } + + /** + * Test checkActionOnRequest method + * + * @param string $action user action + * @param array $params request params + * @param string $controller users controller + * @param bool $expected result expected + * + * @dataProvider dataProviderCheckActionOnRequest + * @return void + */ + public function testCheckActionOnRequest($action, $params, $controller, $expected) + { + $UsersUrl = new UsersUrl(); + Configure::write('Users.controller', $controller); + + $uri = new Uri('/auth/facebook'); + $request = ServerRequestFactory::fromGlobals(); + $request = $request->withUri($uri); + $request = $request->withAttribute('params', $params); + $actual = $UsersUrl->checkActionOnRequest($action, $request); + $this->assertSame($expected, $actual); + } +} From 4d40c6ed92865699438bdb4535fdc79ae14a3eba Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 4 Nov 2018 18:14:09 -0200 Subject: [PATCH 118/685] checking if should load authentication component --- config/users.php | 3 +-- src/Controller/UsersController.php | 7 ++++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/config/users.php b/config/users.php index a44a331d5..06621ba94 100644 --- a/config/users.php +++ b/config/users.php @@ -18,8 +18,6 @@ '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 @@ -127,6 +125,7 @@ ], 'Auth' => [ 'AuthenticationComponent' => [ + 'load' => true, 'loginAction' => [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 16efa9055..2dba7dc18 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller; +use Cake\Utility\Hash; use CakeDC\Users\Controller\Traits\GoogleVerifyTrait; use CakeDC\Users\Controller\Traits\LinkSocialTrait; use CakeDC\Users\Controller\Traits\LoginTrait; @@ -57,7 +58,11 @@ public function initialize() */ protected function loadAuthComponents() { - $this->loadComponent('Authentication.Authentication', Configure::read('Auth.AuthenticationComponent')); + $authenticationConfig = Configure::read('Auth.AuthenticationComponent'); + if (Hash::get($authenticationConfig, 'load')) { + unset($authenticationConfig['config']); + $this->loadComponent('Authentication.Authentication', $authenticationConfig); + } if (Configure::read('Auth.AuthorizationComponent.enable') !== false) { $config = (array)Configure::read('Auth.AuthorizationComponent'); From 952207878a42c5b4638825272ef839484fbfc6f7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 4 Nov 2018 18:26:46 -0200 Subject: [PATCH 119/685] removed invalid configuration Social.authenticator --- config/users.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/users.php b/config/users.php index 06621ba94..8c1c217b4 100644 --- a/config/users.php +++ b/config/users.php @@ -57,8 +57,6 @@ 'Social' => [ // enable social login 'login' => false, - // enable social login - 'authenticator' => 'CakeDC/Users.Social', ], 'GoogleAuthenticator' => [ // enable Google Authenticator From bee7759e79ed45091210df3933f3d4cb0b404e1f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 6 Nov 2018 07:04:35 -0200 Subject: [PATCH 120/685] Adding a default 2fa checker, this allow us to create custom checkers --- .../DefaultTwoFactorAuthenticationChecker.php | 40 +++++++++++ ...woFactorAuthenticationCheckerInterface.php | 23 +++++++ ...aultTwoFactorAuthenticationCheckerTest.php | 68 +++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 src/Auth/DefaultTwoFactorAuthenticationChecker.php create mode 100644 src/Auth/TwoFactorAuthenticationCheckerInterface.php create mode 100644 tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php diff --git a/src/Auth/DefaultTwoFactorAuthenticationChecker.php b/src/Auth/DefaultTwoFactorAuthenticationChecker.php new file mode 100644 index 000000000..021eba05e --- /dev/null +++ b/src/Auth/DefaultTwoFactorAuthenticationChecker.php @@ -0,0 +1,40 @@ +isEnabled(); + } + +} diff --git a/src/Auth/TwoFactorAuthenticationCheckerInterface.php b/src/Auth/TwoFactorAuthenticationCheckerInterface.php new file mode 100644 index 000000000..f64f194ad --- /dev/null +++ b/src/Auth/TwoFactorAuthenticationCheckerInterface.php @@ -0,0 +1,23 @@ +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->assertFalse($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->assertFalse($Checker->isRequired(['id' => 10])); + } + + /** + * Test isRequired method + * + * @return void + */ + public function testIsRequiredEmptyUser() + { + $this->expectException(BadRequestException::class); + Configure::write('Users.GoogleAuthenticator.login'); + $Checker = new DefaultTwoFactorAuthenticationChecker(); + $Checker->isRequired([]); + } +} From 2cd21fe60986c3301e314d4789ecf0390548f8dd Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 6 Nov 2018 08:00:08 -0200 Subject: [PATCH 121/685] Google authenticator component with 2fa checker --- config/users.php | 1 + ...woFactorAuthenticationCheckerInterface.php | 2 +- .../GoogleAuthenticatorComponent.php | 20 ++++++++++++++ .../GoogleAuthenticatorComponentTest.php | 26 +++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index 52bba11e8..25d4806f2 100644 --- a/config/users.php +++ b/config/users.php @@ -118,6 +118,7 @@ ], ], 'GoogleAuthenticator' => [ + 'checker' => 'CakeDC\Users\Auth\DefaultTwoFactorAuthenticationChecker', 'verifyAction' => [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', diff --git a/src/Auth/TwoFactorAuthenticationCheckerInterface.php b/src/Auth/TwoFactorAuthenticationCheckerInterface.php index f64f194ad..e0aea60bc 100644 --- a/src/Auth/TwoFactorAuthenticationCheckerInterface.php +++ b/src/Auth/TwoFactorAuthenticationCheckerInterface.php @@ -9,7 +9,7 @@ interface TwoFactorAuthenticationCheckerInterface * * @return bool */ - public function isEnable(); + public function isEnabled(); /** diff --git a/src/Controller/Component/GoogleAuthenticatorComponent.php b/src/Controller/Component/GoogleAuthenticatorComponent.php index 71fab3cb6..1e38bc2ef 100644 --- a/src/Controller/Component/GoogleAuthenticatorComponent.php +++ b/src/Controller/Component/GoogleAuthenticatorComponent.php @@ -15,6 +15,7 @@ use Cake\Core\Configure; use Cake\Event\Event; use Cake\Utility\Security; +use CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface; use InvalidArgumentException; use RobThree\Auth\TwoFactorAuth; @@ -80,4 +81,23 @@ public function getQRCodeImageAsDataUri($issuer, $secret) { return $this->tfa->getQRCodeImageAsDataUri($issuer, $secret); } + + /** + * Get the two factor authentication checker + * + * @return TwoFactorAuthenticationCheckerInterface + */ + public function getChecker() + { + $className = Configure::read('GoogleAuthenticator.checker'); + + $interfaces = class_implements($className); + $required = 'CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface'; + + if (in_array($required, $interfaces)) { + return new $className(); + } + + throw new InvalidArgumentException("Invalid config for 'GoogleAuthenticator.checker', '$className' does not implement '$required'"); + } } diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index 868c449da..e5b4d2f74 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -14,6 +14,7 @@ use CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotFoundException; +use CakeDC\Users\Auth\DefaultTwoFactorAuthenticationChecker; use Cake\Controller\Controller; use Cake\Core\Configure; use Cake\Core\Plugin; @@ -41,6 +42,7 @@ class GoogleAuthenticatorComponentTest extends TestCase public function setUp() { parent::setUp(); + Configure::write('Error.errorLevel', E_ALL & ~E_DEPRECATED); $this->backupUsersConfig = Configure::read('Users'); Router::reload(); @@ -133,4 +135,28 @@ public function testVerifyCode() $verified = $this->Controller->GoogleAuthenticator->verifyCode($secret, $verificationCode); $this->assertTrue($verified); } + + /** + * Test getChecker method + * + * @return void + */ + public function testGetChecker() + { + $result = $this->Controller->GoogleAuthenticator->getChecker(); + $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'"); + $this->Controller->GoogleAuthenticator->getChecker(); + } } From 8212107375406ed8fbad626700748d2cfc728e1c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 6 Nov 2018 08:16:37 -0200 Subject: [PATCH 122/685] using 2fa checket at login action --- .../DefaultTwoFactorAuthenticationChecker.php | 10 +++------- .../TwoFactorAuthenticationCheckerInterface.php | 2 +- .../Component/GoogleAuthenticatorComponent.php | 13 +++++++++++-- src/Controller/Traits/LoginTrait.php | 13 ++----------- ...DefaultTwoFactorAuthenticationCheckerTest.php | 12 +----------- .../Controller/Traits/LoginTraitTest.php | 16 ++++++++++++++++ 6 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/Auth/DefaultTwoFactorAuthenticationChecker.php b/src/Auth/DefaultTwoFactorAuthenticationChecker.php index 021eba05e..791bb90d4 100644 --- a/src/Auth/DefaultTwoFactorAuthenticationChecker.php +++ b/src/Auth/DefaultTwoFactorAuthenticationChecker.php @@ -18,7 +18,7 @@ class DefaultTwoFactorAuthenticationChecker implements TwoFactorAuthenticationCh */ public function isEnabled() { - return (bool)Configure::read('Users.GoogleAuthenticator.login'); + return Configure::read('Users.GoogleAuthenticator.login') !== false; } /** @@ -28,13 +28,9 @@ public function isEnabled() * * @return bool */ - public function isRequired(array $user) + public function isRequired(array $user = null) { - if (empty($user)) { - throw new BadRequestException("User data can't be empty"); - } - - return $this->isEnabled(); + return empty($user) && $this->isEnabled(); } } diff --git a/src/Auth/TwoFactorAuthenticationCheckerInterface.php b/src/Auth/TwoFactorAuthenticationCheckerInterface.php index e0aea60bc..bd74c982f 100644 --- a/src/Auth/TwoFactorAuthenticationCheckerInterface.php +++ b/src/Auth/TwoFactorAuthenticationCheckerInterface.php @@ -19,5 +19,5 @@ public function isEnabled(); * * @return bool */ - public function isRequired(array $user); + public function isRequired(array $user = null); } \ No newline at end of file diff --git a/src/Controller/Component/GoogleAuthenticatorComponent.php b/src/Controller/Component/GoogleAuthenticatorComponent.php index 1e38bc2ef..7361f8dca 100644 --- a/src/Controller/Component/GoogleAuthenticatorComponent.php +++ b/src/Controller/Component/GoogleAuthenticatorComponent.php @@ -29,6 +29,11 @@ class GoogleAuthenticatorComponent extends Component /** @var \RobThree\Auth\TwoFactorAuth $tfa */ public $tfa; + /** + * @var \CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface + */ + private $checker; + /** * initialize method * @param array $config The config data @@ -89,15 +94,19 @@ public function getQRCodeImageAsDataUri($issuer, $secret) */ public function getChecker() { + if ($this->checker !== null) { + return $this->checker; + } $className = Configure::read('GoogleAuthenticator.checker'); $interfaces = class_implements($className); $required = 'CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface'; if (in_array($required, $interfaces)) { - return new $className(); - } + $this->checker = new $className(); + return $this->checker; + } throw new InvalidArgumentException("Invalid config for 'GoogleAuthenticator.checker', '$className' does not implement '$required'"); } } diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 6e7c7b509..2dba06e50 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -171,7 +171,6 @@ public function login() } $socialLogin = $this->_isSocialLogin(); - $googleAuthenticatorLogin = $this->_isGoogleAuthenticator(); if ($this->request->is('post')) { if (!$this->_checkReCaptcha()) { @@ -181,6 +180,7 @@ public function login() } $user = $this->Auth->identify(); + $googleAuthenticatorLogin = $this->GoogleAuthenticator->getChecker()->isRequired($user); return $this->_afterIdentifyUser($user, $socialLogin, $googleAuthenticatorLogin); } @@ -211,7 +211,7 @@ public function login() */ public function verify() { - if (!Configure::read('Users.GoogleAuthenticator.login')) { + if (!$this->GoogleAuthenticator->getChecker()->isEnabled()) { $message = __d('CakeDC/Users', 'Please enable Google Authenticator first.'); $this->Flash->error($message, 'default', [], 'auth'); @@ -384,13 +384,4 @@ protected function _isSocialLogin() return Configure::read('Users.Social.login') && $this->request->getSession()->check(Configure::read('Users.Key.Session.social')); } - - /** - * Check if we doing Google Authenticator Two Factor auth - * @return bool true if Google Authenticator is enabled - */ - protected function _isGoogleAuthenticator() - { - return Configure::read('Users.GoogleAuthenticator.login'); - } } diff --git a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php index 48619911d..5fa8fcb28 100644 --- a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php +++ b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php @@ -51,18 +51,8 @@ public function testIsRequired() Configure::delete('Users.GoogleAuthenticator.login'); $Checker = new DefaultTwoFactorAuthenticationChecker(); $this->assertFalse($Checker->isRequired(['id' => 10])); - } - /** - * Test isRequired method - * - * @return void - */ - public function testIsRequiredEmptyUser() - { - $this->expectException(BadRequestException::class); - Configure::write('Users.GoogleAuthenticator.login'); $Checker = new DefaultTwoFactorAuthenticationChecker(); - $Checker->isRequired([]); + $this->assertFalse($Checker->isRequired([])); } } diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 47a3d29c5..1d40482e3 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -96,6 +96,10 @@ public function testLoginHappy() $this->Trait->expects($this->once()) ->method('redirect') ->with($redirectLoginOK); + $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) + ->disableOriginalConstructor() + ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) + ->getMock(); $this->Trait->login(); } @@ -129,6 +133,10 @@ public function testAfterIdentifyEmptyUser() $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(); } @@ -409,6 +417,10 @@ public function testVerifyHappy() ->method('is') ->with('post') ->will($this->returnValue(false)); + $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) + ->disableOriginalConstructor() + ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) + ->getMock(); $this->Trait->verify(); } @@ -420,6 +432,10 @@ 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.'); From 63f397b1889cc11d15b1f36c92b8d4518844a8a7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 6 Nov 2018 08:37:36 -0200 Subject: [PATCH 123/685] using 2fa checker at login action with a factory --- .../TwoFactorAuthenticationCheckerFactory.php | 30 ++++++++++++++++ .../GoogleAuthenticatorComponent.php | 25 +------------ .../Component/UsersAuthComponent.php | 3 +- src/Controller/Traits/LoginTrait.php | 5 +-- ...FactorAuthenticationCheckerFactoryTest.php | 36 +++++++++++++++++++ .../GoogleAuthenticatorComponentTest.php | 24 ------------- 6 files changed, 72 insertions(+), 51 deletions(-) create mode 100644 src/Auth/TwoFactorAuthenticationCheckerFactory.php create mode 100644 tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php diff --git a/src/Auth/TwoFactorAuthenticationCheckerFactory.php b/src/Auth/TwoFactorAuthenticationCheckerFactory.php new file mode 100644 index 000000000..83d4d5c6e --- /dev/null +++ b/src/Auth/TwoFactorAuthenticationCheckerFactory.php @@ -0,0 +1,30 @@ +tfa->getQRCodeImageAsDataUri($issuer, $secret); } - - /** - * Get the two factor authentication checker - * - * @return TwoFactorAuthenticationCheckerInterface - */ - public function getChecker() - { - if ($this->checker !== null) { - return $this->checker; - } - $className = Configure::read('GoogleAuthenticator.checker'); - - $interfaces = class_implements($className); - $required = 'CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface'; - - if (in_array($required, $interfaces)) { - $this->checker = new $className(); - - return $this->checker; - } - throw new InvalidArgumentException("Invalid config for 'GoogleAuthenticator.checker', '$className' does not implement '$required'"); - } } diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index f32dff7ee..6bf38d26a 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller\Component; +use CakeDC\Users\Auth\TwoFactorAuthenticationCheckerFactory; use CakeDC\Users\Exception\BadConfigurationException; use Cake\Controller\Component; use Cake\Core\Configure; @@ -55,7 +56,7 @@ public function initialize(array $config) $this->_loadRememberMe(); } - if (Configure::read('Users.GoogleAuthenticator.login')) { + if ((new TwoFactorAuthenticationCheckerFactory())->build()->isEnabled()) { $this->_loadGoogleAuthenticator(); } diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 2dba06e50..8362535f3 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\Controller\Traits; +use CakeDC\Users\Auth\TwoFactorAuthenticationCheckerFactory; use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; @@ -179,8 +180,8 @@ public function login() return; } $user = $this->Auth->identify(); + $googleAuthenticatorLogin = (new TwoFactorAuthenticationCheckerFactory())->build()->isRequired($user); - $googleAuthenticatorLogin = $this->GoogleAuthenticator->getChecker()->isRequired($user); return $this->_afterIdentifyUser($user, $socialLogin, $googleAuthenticatorLogin); } @@ -211,7 +212,7 @@ public function login() */ public function verify() { - if (!$this->GoogleAuthenticator->getChecker()->isEnabled()) { + if (!(new TwoFactorAuthenticationCheckerFactory())->build()->isEnabled()) { $message = __d('CakeDC/Users', 'Please enable Google Authenticator first.'); $this->Flash->error($message, 'default', [], 'auth'); diff --git a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php new file mode 100644 index 000000000..3441fa9e9 --- /dev/null +++ b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php @@ -0,0 +1,36 @@ +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 index e5b4d2f74..247cd3049 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -135,28 +135,4 @@ public function testVerifyCode() $verified = $this->Controller->GoogleAuthenticator->verifyCode($secret, $verificationCode); $this->assertTrue($verified); } - - /** - * Test getChecker method - * - * @return void - */ - public function testGetChecker() - { - $result = $this->Controller->GoogleAuthenticator->getChecker(); - $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'"); - $this->Controller->GoogleAuthenticator->getChecker(); - } } From 7b8e1e74eafb03528fa6362699d35f4f623192be Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 6 Nov 2018 08:57:18 -0200 Subject: [PATCH 124/685] fixed isRequired check --- src/Auth/DefaultTwoFactorAuthenticationChecker.php | 2 +- .../Auth/DefaultTwoFactorAuthenticationCheckerTest.php | 4 ++-- .../Auth/TwoFactorAuthenticationCheckerFactoryTest.php | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Auth/DefaultTwoFactorAuthenticationChecker.php b/src/Auth/DefaultTwoFactorAuthenticationChecker.php index 791bb90d4..0183fc93d 100644 --- a/src/Auth/DefaultTwoFactorAuthenticationChecker.php +++ b/src/Auth/DefaultTwoFactorAuthenticationChecker.php @@ -30,7 +30,7 @@ public function isEnabled() */ public function isRequired(array $user = null) { - return empty($user) && $this->isEnabled(); + return !empty($user) && $this->isEnabled(); } } diff --git a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php index 5fa8fcb28..458616b97 100644 --- a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php +++ b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php @@ -30,7 +30,7 @@ public function testIsEnabled() Configure::delete('Users.GoogleAuthenticator.login'); $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertFalse($Checker->isEnabled()); + $this->assertTrue($Checker->isEnabled()); } /** @@ -50,7 +50,7 @@ public function testIsRequired() Configure::delete('Users.GoogleAuthenticator.login'); $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertFalse($Checker->isRequired(['id' => 10])); + $this->assertTrue($Checker->isRequired(['id' => 10])); $Checker = new DefaultTwoFactorAuthenticationChecker(); $this->assertFalse($Checker->isRequired([])); diff --git a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php index 3441fa9e9..7157c2a8e 100644 --- a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php +++ b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php @@ -32,5 +32,4 @@ public function testGetCheckerInvalidInterface() $this->expectExceptionMessage("Invalid config for 'GoogleAuthenticator.checker', 'stdClass' does not implement 'CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface'"); $result = (new TwoFactorAuthenticationCheckerFactory())->build(); } - } From 42910b0245c9b8723265ab86baa1a6b1de7c2da1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 6 Nov 2018 09:55:37 -0200 Subject: [PATCH 125/685] update file doc --- src/Auth/DefaultTwoFactorAuthenticationChecker.php | 9 +++++++++ src/Auth/TwoFactorAuthenticationCheckerFactory.php | 9 +++++++++ src/Auth/TwoFactorAuthenticationCheckerInterface.php | 10 +++++++++- .../DefaultTwoFactorAuthenticationCheckerTest.php | 9 +++++++++ .../TwoFactorAuthenticationCheckerFactoryTest.php | 11 ++++++++++- 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/Auth/DefaultTwoFactorAuthenticationChecker.php b/src/Auth/DefaultTwoFactorAuthenticationChecker.php index 0183fc93d..e9cb3c16d 100644 --- a/src/Auth/DefaultTwoFactorAuthenticationChecker.php +++ b/src/Auth/DefaultTwoFactorAuthenticationChecker.php @@ -1,4 +1,13 @@ Date: Tue, 6 Nov 2018 10:14:43 -0200 Subject: [PATCH 126/685] removed satooshi/php-coveralls --- composer.json | 3 +-- src/Auth/DefaultTwoFactorAuthenticationChecker.php | 1 - src/Auth/TwoFactorAuthenticationCheckerInterface.php | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 528e23e63..eedf2f94b 100644 --- a/composer.json +++ b/composer.json @@ -39,8 +39,7 @@ "league/oauth2-linkedin": "@stable", "luchianenco/oauth2-amazon": "^1.1", "google/recaptcha": "@stable", - "robthree/twofactorauth": "~1.6.0", - "satooshi/php-coveralls": "dev-master" + "robthree/twofactorauth": "~1.6.0" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", diff --git a/src/Auth/DefaultTwoFactorAuthenticationChecker.php b/src/Auth/DefaultTwoFactorAuthenticationChecker.php index e9cb3c16d..be0c1843f 100644 --- a/src/Auth/DefaultTwoFactorAuthenticationChecker.php +++ b/src/Auth/DefaultTwoFactorAuthenticationChecker.php @@ -41,5 +41,4 @@ public function isRequired(array $user = null) { return !empty($user) && $this->isEnabled(); } - } diff --git a/src/Auth/TwoFactorAuthenticationCheckerInterface.php b/src/Auth/TwoFactorAuthenticationCheckerInterface.php index 3c879c25b..b66e0f330 100644 --- a/src/Auth/TwoFactorAuthenticationCheckerInterface.php +++ b/src/Auth/TwoFactorAuthenticationCheckerInterface.php @@ -28,4 +28,4 @@ public function isEnabled(); * @return bool */ public function isRequired(array $user = null); -} \ No newline at end of file +} From 1e7129bbeaadf32594650950e7d970d567329044 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 6 Nov 2018 10:54:13 -0200 Subject: [PATCH 127/685] using cakephp 3.5 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index eedf2f94b..cee142768 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "cakephp/cakephp": "^3.5.0", + "cakephp/cakephp": "~3.5.14", "cakedc/auth": "^2.0" }, "require-dev": { From 8db1260267e83ea73e0a1c58278fdbcfd0fdae69 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 7 Nov 2018 06:16:28 -0200 Subject: [PATCH 128/685] cs fixes --- src/Auth/TwoFactorAuthenticationCheckerInterface.php | 1 - .../Controller/Component/GoogleAuthenticatorComponentTest.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Auth/TwoFactorAuthenticationCheckerInterface.php b/src/Auth/TwoFactorAuthenticationCheckerInterface.php index b66e0f330..bf59001b8 100644 --- a/src/Auth/TwoFactorAuthenticationCheckerInterface.php +++ b/src/Auth/TwoFactorAuthenticationCheckerInterface.php @@ -19,7 +19,6 @@ interface TwoFactorAuthenticationCheckerInterface */ public function isEnabled(); - /** * Check if two factor authentication is required for a user * diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index 247cd3049..91f7e681c 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -11,10 +11,10 @@ namespace CakeDC\Users\Test\TestCase\Controller\Component; +use CakeDC\Users\Auth\DefaultTwoFactorAuthenticationChecker; use CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotFoundException; -use CakeDC\Users\Auth\DefaultTwoFactorAuthenticationChecker; use Cake\Controller\Controller; use Cake\Core\Configure; use Cake\Core\Plugin; From df95fcdb465a4840434ebfad6423d532c02e7be5 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 7 Nov 2018 06:28:48 -0200 Subject: [PATCH 129/685] Avoid use of string for className in configuration --- config/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index 25d4806f2..45a15f5ec 100644 --- a/config/users.php +++ b/config/users.php @@ -118,7 +118,7 @@ ], ], 'GoogleAuthenticator' => [ - 'checker' => 'CakeDC\Users\Auth\DefaultTwoFactorAuthenticationChecker', + 'checker' => \CakeDC\Users\Auth\DefaultTwoFactorAuthenticationChecker::class, 'verifyAction' => [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', From bb83bb197ab63a7ba0d455b7228cc59fb95b84ae Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 7 Nov 2018 06:30:07 -0200 Subject: [PATCH 130/685] Avoid use of string for className in verification --- src/Auth/TwoFactorAuthenticationCheckerFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Auth/TwoFactorAuthenticationCheckerFactory.php b/src/Auth/TwoFactorAuthenticationCheckerFactory.php index 6994c7d96..8287fdf1d 100644 --- a/src/Auth/TwoFactorAuthenticationCheckerFactory.php +++ b/src/Auth/TwoFactorAuthenticationCheckerFactory.php @@ -29,7 +29,7 @@ public function build() { $className = Configure::read('GoogleAuthenticator.checker'); $interfaces = class_implements($className); - $required = 'CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface'; + $required = TwoFactorAuthenticationCheckerInterface::class; if (in_array($required, $interfaces)) { return new $className(); From a2901178c2b60e4947e84e8ea039244e75853a57 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 7 Nov 2018 06:30:54 -0200 Subject: [PATCH 131/685] Removed unused property --- src/Controller/Component/GoogleAuthenticatorComponent.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Controller/Component/GoogleAuthenticatorComponent.php b/src/Controller/Component/GoogleAuthenticatorComponent.php index 088e979bb..215e96853 100644 --- a/src/Controller/Component/GoogleAuthenticatorComponent.php +++ b/src/Controller/Component/GoogleAuthenticatorComponent.php @@ -29,11 +29,6 @@ class GoogleAuthenticatorComponent extends Component /** @var \RobThree\Auth\TwoFactorAuth $tfa */ public $tfa; - /** - * @var \CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface - */ - private $checker; - /** * initialize method * @param array $config The config data From 0e7bc30f091168ae56e9364a38fa19d95d53a09a Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 7 Nov 2018 06:38:04 -0200 Subject: [PATCH 132/685] added get method for 2fa checker --- src/Controller/Traits/LoginTrait.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 8362535f3..26decf418 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -180,9 +180,12 @@ public function login() return; } $user = $this->Auth->identify(); - $googleAuthenticatorLogin = (new TwoFactorAuthenticationCheckerFactory())->build()->isRequired($user); - return $this->_afterIdentifyUser($user, $socialLogin, $googleAuthenticatorLogin); + return $this->_afterIdentifyUser( + $user, + $socialLogin, + $this->getTwoFactorAuthenticationChecker()->isRequired($user) + ); } if (!$this->request->is('post') && !$socialLogin) { @@ -212,7 +215,7 @@ public function login() */ public function verify() { - if (!(new TwoFactorAuthenticationCheckerFactory())->build()->isEnabled()) { + if (!$this->getTwoFactorAuthenticationChecker()->isEnabled()) { $message = __d('CakeDC/Users', 'Please enable Google Authenticator first.'); $this->Flash->error($message, 'default', [], 'auth'); @@ -385,4 +388,14 @@ protected function _isSocialLogin() return Configure::read('Users.Social.login') && $this->request->getSession()->check(Configure::read('Users.Key.Session.social')); } + + /** + * Get the configured two factory authentication + * + * @return \CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface + */ + protected function getTwoFactorAuthenticationChecker() + { + return (new TwoFactorAuthenticationCheckerFactory())->build(); + } } From 70d8528a3c971faacece51cf65b1f147b6c6acd0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 7 Nov 2018 06:38:26 -0200 Subject: [PATCH 133/685] removed unused code --- .../Controller/Component/GoogleAuthenticatorComponentTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php index 91f7e681c..71a3f76e5 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php @@ -42,7 +42,6 @@ class GoogleAuthenticatorComponentTest extends TestCase public function setUp() { parent::setUp(); - Configure::write('Error.errorLevel', E_ALL & ~E_DEPRECATED); $this->backupUsersConfig = Configure::read('Users'); Router::reload(); From ed921bf02e657c6d3dcc3436c38f6c70e0c8cfa3 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 7 Nov 2018 06:42:16 -0200 Subject: [PATCH 134/685] Added method to get two factor authentication checker --- src/Controller/Component/UsersAuthComponent.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index 6bf38d26a..9f1c6e528 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -56,7 +56,7 @@ public function initialize(array $config) $this->_loadRememberMe(); } - if ((new TwoFactorAuthenticationCheckerFactory())->build()->isEnabled()) { + if ($this->getTwoFactorAuthenticationChecker()->isEnabled()) { $this->_loadGoogleAuthenticator(); } @@ -232,4 +232,14 @@ protected function _isActionAllowed($requestParams = []) return false; } + + /** + * Get the configured two factory authentication + * + * @return \CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface + */ + protected function getTwoFactorAuthenticationChecker() + { + return (new TwoFactorAuthenticationCheckerFactory())->build(); + } } From 371ed488e6adb42404b773422fe2fb451e90427e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 7 Nov 2018 07:18:45 -0200 Subject: [PATCH 135/685] Merge branch 'feature/2fa-checker' into feature/develop-2fa-checker --- composer.json | 4 ++-- src/Controller/Component/SetupComponent.php | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index cee142768..2609599e4 100644 --- a/composer.json +++ b/composer.json @@ -27,8 +27,8 @@ "source": "https://github.com/CakeDC/users" }, "require": { - "cakephp/cakephp": "~3.5.14", - "cakedc/auth": "^2.0" + "cakephp/cakephp": "^3.6", + "cakedc/auth": "^3.0" }, "require-dev": { "phpunit/phpunit": "^5.0", diff --git a/src/Controller/Component/SetupComponent.php b/src/Controller/Component/SetupComponent.php index 1821417c1..dc20cb060 100644 --- a/src/Controller/Component/SetupComponent.php +++ b/src/Controller/Component/SetupComponent.php @@ -8,17 +8,15 @@ * @copyright Copyright 2010 - 2017, Cake Development Corporation (https://www.cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ - namespace CakeDC\Users\Controller\Component; - use Cake\Controller\Component; use Cake\Core\Configure; class SetupComponent extends Component { /** - * @param array $config + * @param array $config component configuration * @throws \Exception */ public function initialize(array $config) @@ -29,8 +27,7 @@ public function initialize(array $config) if ($this->getController()->getRequest()->getParam('plugin', null) === $plugin && $this->getController()->getRequest()->getParam('controller') === $controller ) { - $this->getController()->Auth->allow(['login']); } } -} \ No newline at end of file +} From 67a44ff84d9e63d45693da4775f51c9ad098ab99 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 7 Nov 2018 08:07:51 -0200 Subject: [PATCH 136/685] Dispatch event 'after login' at verify action --- src/Controller/Traits/LoginTrait.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 0af028217..c29149053 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -285,6 +285,10 @@ public function verify() $this->request->getSession()->delete('temporarySession'); $this->Auth->setUser($user); + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_LOGIN, ['user' => $user]); + if (is_array($event->result)) { + return $this->redirect($event->result); + } $url = $this->Auth->redirectUrl(); return $this->redirect($url); From 01245c2ae6d2c2353166558b51b8d27b8e1d6a6c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 7 Nov 2018 08:11:09 -0200 Subject: [PATCH 137/685] Dispatch event 'after login' at verify action --- tests/TestCase/Controller/Traits/LoginTraitTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 6b0abdd25..03b4c2636 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -620,6 +620,7 @@ 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']) From 7ff3b71b5c4feb6af9de163a5f58aaf9fcaec278 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 9 Nov 2018 10:42:56 -0200 Subject: [PATCH 138/685] Don't overwrite on error --- src/Controller/Traits/PasswordManagementTrait.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 467c0a705..9cdb9fcdb 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -70,9 +70,9 @@ public function changePassword() if ($user->errors()) { $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); } else { - $user = $this->getUsersTable()->changePassword($user); - if ($user) { - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_CHANGE_PASSWORD, ['user' => $user]); + $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); } From 024f0ec33488d72bdedde12792faccc562bda9ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 13 Nov 2018 07:52:20 +0000 Subject: [PATCH 139/685] refs #rename-tr-language-files rename tr language files --- src/Locale/tr_TR/{tr_TR.mo => Users.mo} | Bin src/Locale/tr_TR/{tr_TR.po => Users.po} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/Locale/tr_TR/{tr_TR.mo => Users.mo} (100%) rename src/Locale/tr_TR/{tr_TR.po => Users.po} (100%) diff --git a/src/Locale/tr_TR/tr_TR.mo b/src/Locale/tr_TR/Users.mo similarity index 100% rename from src/Locale/tr_TR/tr_TR.mo rename to src/Locale/tr_TR/Users.mo diff --git a/src/Locale/tr_TR/tr_TR.po b/src/Locale/tr_TR/Users.po similarity index 100% rename from src/Locale/tr_TR/tr_TR.po rename to src/Locale/tr_TR/Users.po From 1a241767400453421af523fffe780188f974a236 Mon Sep 17 00:00:00 2001 From: Fahad Alrahbi Date: Tue, 13 Nov 2018 12:58:55 +0400 Subject: [PATCH 140/685] Add Arabic translation --- src/Locale/ar_OM/Users.mo | Bin 0 -> 18521 bytes src/Locale/ar_OM/Users.po | 819 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 819 insertions(+) create mode 100644 src/Locale/ar_OM/Users.mo create mode 100644 src/Locale/ar_OM/Users.po 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 zcmchddyrgJoyV_;piu~lD7eb5^B1xEp1P5zTcCD=~A6saxYqx*kx>dNl<+?sr-E!I2=X=h%x9{!g z&I7i#YfgXfJ&)h{o!{&H&gpsXb!UGv;PW-grIg>iA_!gpzw>Io_h~$|67T>hy59sPif@A#fjdR)VD- z@ACB}a1!;q!9M^W@b3pa9s|3ne;O1YzXZ<${~Z*+{{e>JSxl;R=fFi^71Vs=;8gJ2 z;5FbcK=E@KlXZb}LGi!dV;R)C?gh2pt)Te(D5&*)8WbO20H=WaLFwtQJ$?^-4evh! zHUB??=YhWm#qYTojmAv|t$sn-%?%#k4ZfN85pWv#DNy5|23LUJ0dEE`VG(zLcY@c0 z$G{oj&%rl>7xBeXgD&uLuoqPQAYYn+ z>not-b1x`5dq4wz5tN-i16~b23rg<)>Dy;w{F-MuC_ftpMgIX%a{mg*U+_3z(#y9& z$@2%G`2Gj*N>IireNO{rAJ>7B<9bl~*$v8$KL%P?BTyWc0e2!gS$XP8Qcpl0v`n52|fp|0O#T~;%^ryzCI61pT|MX z`*l!!e-m5)eiwW>I2oax3tk9Hzn6gWtGVFeml3DIJ9$43C5v7jl)NgS{NQ0wdjAf% z0ek_x794vM-CH0geXas~!27`Y;MYJ@5d0n#ol7xt@i))o z3h-^b=fLy9QSde32~ctKFTwl4AAqv!yHUzK@E%a~#=wQ(cflp#Yf%zQ3ho4N1b2d3 z*I#)25%@~pf9>C205Rp@LYP;-*&dgIT3qT-+&r738C>A%mL+x5%>srANVnFDo(N)JPIxYXUqst-#@9Q*XF%E6g*Q9j!$e*&f7OK=X^cQ5#5@NdCK!4EEWd|io=iof~b ztH5=j?C@@n1#pn}5%A^UPr!4*=Rr&>_&KQgro9~-14ZkrlqV^dQ8c$c@1uy{dno#R z#DVpJJ9+*jMf&}kuYVkbq>bsSl5HZA;7=)%`*w;xh|_)^mc)udj+>pmiyYB9tE-!+{DJS*QkQeGRlyBa{Eg+&mZ^iviGWg{u7UL!MFNn>F2!^ z>Hl8J0m>tk0m@{GKA)jXqU@o3o)Ui^;Nc6DW4>YvC_B^Vqm)0UtfgRX0VWmfqP(1< zPnQF0C;dFXnerCON?(7K$5(>WDe{+BQ0}9|ANj@;l&{1U;35Bf5Zpq!i&CVVONl?9 z^h2%4uMpa-0%T-b8snTuix@qR$dauYGcH!av$Q_5-}Eqiph(p97Cl-blHFQlc2j4$8YI z9Ta`W^mSupC@h-(LRhKHpE6h&8Csw3FBMJl)KMr6cI1mwOjyo`9qaSCTvVJtrCJ`2 zrrdPnH5z=Axjic92S$PgtCpB*X=79j7WDT=LsheO+&V*hv zgQ*O|Q>8L6TqwY4zval{W*A_osSHK^`GI`D8LmX-M$1TPxNJht`1+_EH8oXA{rRw9 zkW#*A((NqSEP{62U+-G1dk1nkv(8S%LuiW87I++r%3*F3l*EKvWK^lONgwiC6kK^5o?@kKG^jkl+dnQIjThJj{@z?mW3&d znZh8X6qbX9>%-z;WL9A;TT10z{65t5F2$5fg~*bbAlikc;y}K<$uvflip8kEYPRI7 z>&0V04^>3DbX9B^%q5XaX-+FM%}^lv=8K)dLJUlHwQ#sxj*vn!*Pi%-?d z)Q2)Xv3RMZ7;cLESar`Dwx!u)g}68$6>|2`^p?w|GLPLK3Kr+fm8w}G8t&1OyR}pr zL|qGp(Oj{b?+>eTFKY=~!b)ZeW6dOZd)`j6Bo{1klLSi!tV0&^#f>Iku|C{iLi+vH z!idS`D?^2FB+4bq>MsqA*Z~8jLZP%pCLZQ;5U&`_-+JAasL%A3OIzd$GK(ce>&~&> z8}CCyrVpkq7z`0SRgumS+vK5-d|((syaN8Z6IODw=0{Y)8{IS82!w zLj|WWSYFBz1o4~|#G`czPkKn)C;j5gOf~ZL#+x`;f%S%1Q>mQ)KuYN@O5**MYOpE} z8u5cc_(T^M+rvV^T6-nwmuc1l+>DLUX-D#;8iUtk#(fcyEuJK^AH+mFNf%DS3IZjP zX)Z~&e|^;NY9i~osw&|v#o@^5Ysjz2xd`4{(vB0Xa^&1_tJ4=Z{>&T(?vhBCHYBG4 z=_uyw%;=^@M#Zp?sL?WbSRHr9a}ZRJVVKy_ga%pAgv!`T4gO_C*0x7egS1vmo2_4} zW22#hEPIW5Y1@W57l&fKw&Tsbak{T+SG@D3F@o0x8%(2F0)dcv68d()z+$V z*@FgF8#}vujaP&~loe$5s(5udPrIqF_Kl=VW(V>8rKDtx(z%AqyU8bZXim~v^xK>d zGb^@AO{TH=*=lSp&{q-*G8NGeOC5|4^a zBhHJH6elN33^4~7w;VQ)kdzy}JA*aDeVfQk)+mv*af>}Q%Jl@w#BK7qmKeKH1{thH z{{2nqk;#?VjbwhCLiR%2ClOu?8yJj=B&;M_oyNOZl7rc?$)?)Qbi{<^Gb6A{xS1U& zY4h2HmvmCCwTo4IAn0s#CqfyuxwJQzwY_9?+)EUE&o+xt&kTFMyPa`DV}o}!CEHH( zn54n?w;81dJK@<*n2~EDy5?ODy_72M9JJ1D7g)60gRI`|JmnzShm3lj~bs75Jmu!Q~CfzYHL`OGyb!RxNyv;$?60=_Hk0m~v zPU>?}hn+`W=Au&4luY90l)d39u{zV-sVUWPg>2!MRP=(GBS zgy*W7FL2H$d?=bO3^zuL78(($5E_P+gxXsIoh@XX3ro2uThmXC_|Lm6ztgOZk8{E8 z`DjaUM^xx9ZHi{v4EJ4}b3=B~c(GWNGDl`n3tQ;)s`2TGOSZfbXlhQb8wWUYnEZfj z{chKRnFqo`C5j11xU|{~a6*{GYpUo}IYz1IhO8%Mkuk zxyv`)P=6J`)QJ;_rRh*llavo>#Y*dGPWr}st`@4Jm}^WFn2ql)F(HX1TWg%h6JKt` zayvuzBw|CGgk-bohL4Rz)r3GQ803q6rF*PtNQJN zu9&oH<=PH=?LljYE}nYKtgi049o=0W-E+*W**$Zvy}FAJ9XnRDP*G|0o7d6Z-O)YU zbkFLUGyCeUIrLk`X>2$gj5^jv;iew5Y{80K*DbiU*WB2Sl_ve4+^NO z^&O^mu)eK!Ko3vU#_D@&PrBZtwPTDpTsy+poyOE23h1~qL&?;4)_0lO@!FxZZs?CX`eU>mHT6C2 z?EtGt*37!=+u??V)pynRnlo60K`6UwkFlOZftBAVFJrtuOgSh*yJ}A`)02oH&Du_w z-do?L4qNRblJ#<_Z+9X??z?KEnH~or@fhRiEL|O`9fo6G4lr3-5h&>ZD}n>p@gQ;< ztsRfYiASVJ6-?MEc$7R2$K5?oOx~_VY>SDYw!e0QhplKgy~Lol&(+s=XX*`eA7QE^ zY%?4lxQx>^G>h3+d&&y#gyUfpt2$^GHg-x<6OA?2E`qT(JsO+%q1xm1t?r6i)>_{! znMm{27$$Vzr$xf=ZgrBz(3x=wE;fTf#$w0Z>=m|k0nK?_rWsrO6D;O9Q#>kxJ|!}k zEi6Gmr0EYOxfN?|?%-*(>HuT1{|pzr#FhnJ=h$s#5}TL^uE`TdWHTPdQ`30o%{%EB z+VF1gE!EUM;*>RJJ>cPZC5Ir0T{?>x(+c+?fU)}homyVT)b>;H1XT|Q872{{4-2BT zqi#jFACgb0FUmNTTUk8^xRlgwNu*R2*S8hiA!`s;8RN26?>OoHfruiJ_F?4IJi!$hImz@20Eb@ z_EoFcNaSqk{3zV+BRl0b*v2-@+uuw!*bV42hVh|O>r|SZs&NKywUfp#p7H&5n^GUN zuIbs+AmBrxwiCIYY~%^KiQP@!JjUJED$CAS^w=>4k#YVS^wwQrQ3DEG<2hXF7Ihe|En@HAo2VRyg zo;Ed``krf00ruqBPeP6}N#zsJ_nWTM$yHU|Sg<>DE zxAFF6H0t>FswF35aW2KcCMISLT1BQ_5t?X3@JX4WmOLTPO57+t7yK#6qb^Cu22Htv zPfKLde&cT!>3uWum5sxEc4stJa7iccIc^7xNxMoNh~k?RZOxG+c+$;W87Ntp&5gu;S{zl z_LNXsytSvD3u`(>-@>Xf_XMUXHAl31Pz~^ltVfY_*j|%%JruhNtqN z7c&OqJrkd4r=d17Fc@U37~RBaOXH015n6{_O99y(Mc+r*ifZXRSedR4$F9{_rtLn5 z36a;p>{#uo=0Qq;FxKs`9A_-nl*f}1#CJ<7;fRRIxnVoAaT^fCa@78sT9J$@NlM10 zKF3hn(5xY3G}$taF;SbGGN|px8)cK4JUM|Tj$J;Yr zcE+R|J4)Kbk;pOhM6Ox?@abAw>>fIA+bcgNJdGPE=Z*1TCUz;W5?-wqN9V#%Mw7`d zA5r${*U;jsBFq1NXxbCCAJDkNvOj6B<5v+aGJREnKK3yERz!d=`YXrwm!W}=A{ES;g(e{-bJ*BBfgZcB?b`ZcN10DL znq;WAAM)Y_D${e2@AI(A55k zjZ4vvxomeIw7t3db*9+yhyQqR^U7vUumD8?LLqU}4YeI=kMQnIqon}60F#ZTQ%2YJ znBe#D7P*-054r2s&s~G<2dT{-k_$1oGM*7$yiykBGnnqnf6WR$Bn={kv|uwQp;ET%kBcHMKpeHXr|N? zG}pYuAashT$S#rOx0m`Sf;^xXdE4kY1jv3296lU5vRc=fTOX?Q9v zj#rFcU3QnjYi|AW(Z|A*ABzVZJ_-gLAGE(?3F3 +# +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}" From 70cef3d61f4d8eb86d68fbe0facb95a0f6b26968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 13 Nov 2018 09:34:06 +0000 Subject: [PATCH 141/685] Update .semver --- .semver | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.semver b/.semver index ae45234e5..fba2c8e3f 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- -:major: 7 +:major: 8 :minor: 0 -:patch: 2 +:patch: 0 :special: '' From 617d7bbec1c60fd14c09899984a11b383e8707af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 13 Nov 2018 09:48:31 +0000 Subject: [PATCH 142/685] Update CHANGELOG.md --- CHANGELOG.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b96bd7d4f..7f5ce5ba3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,15 @@ Changelog Releases for CakePHP 3 ------------- -* 7.0.1 +* 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 From 3570ad2d3ab95554b2a40f5922ac53d012ac3422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Tue, 13 Nov 2018 09:49:38 +0000 Subject: [PATCH 143/685] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c213f6a7..5aac7a803 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| ^3.6 | [master](https://github.com/cakedc/users/tree/master) | 7.0.0 | stable | +| ^3.6 | [master](https://github.com/cakedc/users/tree/master) | 8.0.0 | 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 | From feb9c369ebc84cd2129658f55b6d68da229ef299 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 14 Nov 2018 07:53:51 -0200 Subject: [PATCH 144/685] avoid type check error --- src/Controller/Traits/LoginTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index c29149053..ff641ce8e 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -184,7 +184,7 @@ public function login() return $this->_afterIdentifyUser( $user, $socialLogin, - $this->getTwoFactorAuthenticationChecker()->isRequired($user) + $user && $this->getTwoFactorAuthenticationChecker()->isRequired($user) ); } From 81b9b423f02876f1312720c7230cb35089a2f612 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 14 Nov 2018 08:07:20 -0200 Subject: [PATCH 145/685] Making sure 2fa redirect preserve query string from login action --- src/Controller/Traits/LoginTrait.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index ff641ce8e..1a24ca162 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -215,18 +215,24 @@ public function login() */ public function verify() { + $loginUrl = array_merge( + Configure::read('Auth.loginAction'), + [ + '?' => $this->request->getQueryParams() + ] + ); if (!$this->getTwoFactorAuthenticationChecker()->isEnabled()) { $message = __d('CakeDC/Users', 'Please enable Google Authenticator first.'); $this->Flash->error($message, 'default', [], 'auth'); - return $this->redirect(Configure::read('Auth.loginAction')); + return $this->redirect($loginUrl); } $temporarySession = $this->request->getSession()->read('temporarySession'); if (!is_array($temporarySession) || empty($temporarySession)) { $this->Flash->error(__d('CakeDC/Users', 'Invalid request.'), 'default', [], 'auth'); - return $this->redirect(Configure::read('Auth.loginAction')); + return $this->redirect($loginUrl); } $secret = Hash::get($temporarySession, 'secret'); @@ -251,7 +257,7 @@ public function verify() $message = $e->getMessage(); $this->Flash->error($message, 'default', [], 'auth'); - return $this->redirect(Configure::read('Auth.loginAction')); + return $this->redirect($loginUrl); } } $secretDataUri = $this->GoogleAuthenticator->getQRCodeImageAsDataUri( @@ -297,7 +303,7 @@ public function verify() $message = __d('CakeDC/Users', 'Verification code is invalid. Try again'); $this->Flash->error($message, 'default', [], 'auth'); - return $this->redirect(Configure::read('Auth.loginAction')); + return $this->redirect($loginUrl); } } } @@ -334,7 +340,9 @@ protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthen // until the GA verification is checked $this->request->getSession()->write('temporarySession', $user); $url = Configure::read('GoogleAuthenticator.verifyAction'); - + $url = array_merge($url, [ + '?' => $this->request->getQueryParams() + ]); return $this->redirect($url); } From 75f199a610d9e915fdd8846282be5cc91e9f2215 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 14 Nov 2018 08:10:19 -0200 Subject: [PATCH 146/685] Making sure 2fa redirect preserve query string from login action --- tests/TestCase/Controller/Traits/LoginTraitTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 03b4c2636..a897f0f50 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -763,7 +763,8 @@ public function testVerifyPostInvalidCode() 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', - 'prefix' => false + 'prefix' => false, + '?' => [] ]); $this->assertFalse($this->table->exists([ From c515cd3e355aeed5e7504fb9d689dd2c9c886244 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 14 Nov 2018 08:13:13 -0200 Subject: [PATCH 147/685] phpcs fix --- src/Controller/Traits/LoginTrait.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 1a24ca162..10a99ff12 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -343,6 +343,7 @@ protected function _afterIdentifyUser($user, $socialLogin = false, $googleAuthen $url = array_merge($url, [ '?' => $this->request->getQueryParams() ]); + return $this->redirect($url); } From 4cbe85be9fe66bf2cd5d9e27701564aa05c42209 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 15 Nov 2018 14:32:42 -0200 Subject: [PATCH 148/685] Locator was refactored into indentifier --- src/Social/Locator/DatabaseLocator.php | 106 ----------- src/Social/Locator/LocatorInterface.php | 16 -- .../Social/Locator/DatabaseLocatorTest.php | 170 ------------------ 3 files changed, 292 deletions(-) delete mode 100644 src/Social/Locator/DatabaseLocator.php delete mode 100644 src/Social/Locator/LocatorInterface.php delete mode 100644 tests/TestCase/Social/Locator/DatabaseLocatorTest.php diff --git a/src/Social/Locator/DatabaseLocator.php b/src/Social/Locator/DatabaseLocator.php deleted file mode 100644 index b4b4a3843..000000000 --- a/src/Social/Locator/DatabaseLocator.php +++ /dev/null @@ -1,106 +0,0 @@ - 'all', - ]; - - /** - * DatabaseLocator constructor. - * - * @param array $config optional config - */ - public function __construct(array $config = []) - { - $config += ['userModel' => Configure::read('Users.table')]; - $this->setConfig($config); - } - - /** - * Get or create the user based on the $rawData - * - * @param array $rawData mapped social user data - * @return User - */ - public function getOrCreate(array $rawData): User - { - if (!$this->getConfig('userModel')) { - throw new InvalidSettingsException(__d('CakeDC/Users', 'Users table is not defined')); - } - - $user = $this->_socialLogin($rawData); - - if (!$user) { - throw new RecordNotFoundException(__d('CakeDC/Users', 'Could not locate user')); - } - // If new SocialAccount was created $user is returned containing it - if ($user->get('social_accounts')) { - $this->dispatchEvent(Plugin::EVENT_AFTER_SOCIAL_REGISTER, compact('user')); - } - - $user = $this->findUser($user)->firstOrFail(); - - return $user; - } - - /** - * Get query object for fetching user from database. - * - * @param User $user The user. - * - * @return \Cake\Orm\Query - */ - protected function findUser($user) - { - $userModel = $this->getConfig('userModel'); - $table = TableRegistry::getTableLocator()->get($userModel); - $finder = $this->getConfig('authFinder'); - - $primaryKey = (array)$table->getPrimaryKey(); - - $conditions = []; - foreach ($primaryKey as $key) { - $conditions[$table->aliasField($key)] = $user->get($key); - } - - return $table->find($finder)->where($conditions); - } - - /** - * @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/Social/Locator/LocatorInterface.php b/src/Social/Locator/LocatorInterface.php deleted file mode 100644 index 632be43ec..000000000 --- a/src/Social/Locator/LocatorInterface.php +++ /dev/null @@ -1,16 +0,0 @@ - 'test-token', - 'expires' => 1490988496 - ]); - - $data = [ - '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' - ]; - - $user = (new Facebook())($data); - $user['provider'] = 'facebook'; - - $this->Locator = new DatabaseLocator(); - $result = $this->Locator->getOrCreate($user); - $this->assertInstanceOf('CakeDC\Users\Model\Entity\User', $result); - $this->assertNotEmpty($result->id); - $this->assertEquals('test@gmail.com', $result->email); - $this->assertEquals('test', $result->username); - } - - /** - * Test getOrCreate method error in social login - * - * @return void - */ - public function testGetOrCreateErrorSocialLogin() - { - $Token = new \League\OAuth2\Client\Token\AccessToken([ - 'access_token' => 'test-token', - 'expires' => 1490988496 - ]); - $this->Locator = $this->getMockBuilder(DatabaseLocator::class)->setMethods([ - '_socialLogin' - ])->getMock(); - $this->Locator->expects($this->once()) - ->method('_socialLogin') - ->will($this->returnValue(false)); - - $data = [ - 'token' => $Token, - 'id' => '1', - 'name' => '', - 'first_name' => 'Test', - 'last_name' => 'User', - 'email' => 'test@gmail.com', - 'hometown' => [ - 'id' => '108226049197930', - 'name' => 'Madrid' - ], - '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' - ]; - - $user = (new Facebook())($data); - $user['provider'] = 'facebook'; - - $this->expectException(RecordNotFoundException::class); - $this->Locator->getOrCreate($user); - } - - /** - * Test getOrCreate method invalid user model - * - * @return void - */ - public function testGetOrCreateInvalidUserModel() - { - $Token = new \League\OAuth2\Client\Token\AccessToken([ - 'access_token' => 'test-token', - 'expires' => 1490988496 - ]); - - $data = [ - 'token' => $Token, - 'id' => '1', - 'name' => '', - 'first_name' => 'Test', - 'last_name' => 'User', - 'email' => 'test@gmail.com', - 'hometown' => [ - 'id' => '108226049197930', - 'name' => 'Madrid' - ], - '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' - ]; - - $this->Locator = new DatabaseLocator([ - 'userModel' => false - ]); - $user = (new Facebook())($data); - $user['provider'] = 'facebook'; - - $this->expectException(InvalidSettingsException::class); - $this->Locator->getOrCreate($user); - } -} From 7f4d421de21765743f9ded4b940119487c45d3d2 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 15 Nov 2018 14:48:25 -0200 Subject: [PATCH 149/685] removed unused exceptions --- src/Exception/BadConfigurationException.php | 28 ----------- .../MissingEventListenerException.php | 30 ------------ .../MissingProviderConfigurationException.php | 31 ------------- src/Exception/MissingProviderException.php | 28 ----------- .../BadConfigurationExceptionTest.php | 43 ----------------- .../MissingEventListenerExceptionTest.php | 45 ------------------ ...singProviderConfigurationExceptionTest.php | 46 ------------------- .../MissingProviderExceptionTest.php | 43 ----------------- 8 files changed, 294 deletions(-) delete mode 100644 src/Exception/BadConfigurationException.php delete mode 100644 src/Exception/MissingEventListenerException.php delete mode 100644 src/Exception/MissingProviderConfigurationException.php delete mode 100644 src/Exception/MissingProviderException.php delete mode 100644 tests/TestCase/Exception/BadConfigurationExceptionTest.php delete mode 100644 tests/TestCase/Exception/MissingEventListenerExceptionTest.php delete mode 100644 tests/TestCase/Exception/MissingProviderConfigurationExceptionTest.php delete mode 100644 tests/TestCase/Exception/MissingProviderExceptionTest.php diff --git a/src/Exception/BadConfigurationException.php b/src/Exception/BadConfigurationException.php deleted file mode 100644 index 548a67afb..000000000 --- a/src/Exception/BadConfigurationException.php +++ /dev/null @@ -1,28 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/MissingEventListenerExceptionTest.php b/tests/TestCase/Exception/MissingEventListenerExceptionTest.php deleted file mode 100644 index f46e3a0a5..000000000 --- a/tests/TestCase/Exception/MissingEventListenerExceptionTest.php +++ /dev/null @@ -1,45 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/MissingProviderConfigurationExceptionTest.php b/tests/TestCase/Exception/MissingProviderConfigurationExceptionTest.php deleted file mode 100644 index 7633002ad..000000000 --- a/tests/TestCase/Exception/MissingProviderConfigurationExceptionTest.php +++ /dev/null @@ -1,46 +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()); - } -} From bd91c2fe8d34c8865b1f264799caa35c28652bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 15 Nov 2018 17:12:42 +0000 Subject: [PATCH 150/685] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index fba2c8e3f..fd30894e0 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 8 :minor: 0 -:patch: 0 +:patch: 1 :special: '' From 0a36fa6eca384332176e891c3aab563da3ab44a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 15 Nov 2018 17:13:20 +0000 Subject: [PATCH 151/685] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f5ce5ba3..5fc599209 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ Changelog Releases for CakePHP 3 ------------- +* 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 From 989873e6606ad1cb5f97f1bdb7861a84b8d3601a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 15 Nov 2018 17:13:44 +0000 Subject: [PATCH 152/685] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5aac7a803..dac5934c8 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| ^3.6 | [master](https://github.com/cakedc/users/tree/master) | 8.0.0 | stable | +| ^3.6 | [master](https://github.com/cakedc/users/tree/master) | 8.0.1 | 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 | From 1e4ea61b35de1c74ff509ebee9eb42382beb8c09 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 15 Nov 2018 15:58:19 -0200 Subject: [PATCH 153/685] Rename GoogleAuthenticator to OneTimePasswordAuthenticator --- .../Google-Two-Factor-Authenticator.md | 6 +-- Docs/Documentation/Installation.md | 4 +- config/permissions.php | 2 +- config/routes.php | 6 +-- config/users.php | 4 +- src/Authentication/AuthenticationService.php | 2 +- ...OneTimePasswordAuthenticatorComponent.php} | 18 ++++---- ...ait.php => OneTimePasswordVerifyTrait.php} | 10 ++--- .../Traits/PasswordManagementTrait.php | 4 +- src/Controller/UsersController.php | 10 ++--- ...neTimePasswordAuthenticatorMiddleware.php} | 2 +- src/Plugin.php | 8 ++-- src/Template/Users/edit.ctp | 4 +- .../AuthenticationServiceTest.php | 4 +- ...imePasswordAuthenticatorComponentTest.php} | 32 +++++++------- ...php => OneTimePasswordVerifyTraitTest.php} | 42 +++++++++---------- .../Traits/PasswordManagementTraitTest.php | 6 +-- tests/TestCase/PluginTest.php | 34 +++++++-------- tests/TestCase/Utility/UsersUrlTest.php | 4 +- 19 files changed, 101 insertions(+), 101 deletions(-) rename src/Controller/Component/{GoogleAuthenticatorComponent.php => OneTimePasswordAuthenticatorComponent.php} (72%) rename src/Controller/Traits/{GoogleVerifyTrait.php => OneTimePasswordVerifyTrait.php} (92%) rename src/Middleware/{GoogleAuthenticatorMiddleware.php => OneTimePasswordAuthenticatorMiddleware.php} (96%) rename tests/TestCase/Controller/Component/{GoogleAuthenticatorComponentTest.php => OneTimePasswordAuthenticatorComponentTest.php} (66%) rename tests/TestCase/Controller/Traits/{GoogleVerifyTraitTest.php => OneTimePasswordVerifyTraitTest.php} (84%) diff --git a/Docs/Documentation/Google-Two-Factor-Authenticator.md b/Docs/Documentation/Google-Two-Factor-Authenticator.md index 99245ce76..47b128bda 100644 --- a/Docs/Documentation/Google-Two-Factor-Authenticator.md +++ b/Docs/Documentation/Google-Two-Factor-Authenticator.md @@ -16,7 +16,7 @@ Enable google authenticator in your bootstrap.php file: Config/bootstrap.php ``` -Configure::write('Users.GoogleAuthenticator.login', true); +Configure::write('Users.OneTimePasswordAuthenticator.login', true); ``` How does it work @@ -28,9 +28,9 @@ the QR code shown (image 1). 1) Validation code page - + 2) Google Authentation app - + diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 18b244230..477df992e 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -40,10 +40,10 @@ If you want to use Google Authenticator features... composer require robthree/twofactorauth:"^1.5.2" ``` -NOTE: you'll need to enable `Users.GoogleAuthenticator.login` +NOTE: you'll need to enable `Users.OneTimePasswordAuthenticator.login` ``` -Configure::write('Users.GoogleAuthenticator.login', true); +Configure::write('Users.OneTimePasswordAuthenticator.login', true); ``` Creating Required Tables diff --git a/config/permissions.php b/config/permissions.php index 83ad91758..08534fc29 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -106,7 +106,7 @@ 'role' => '*', 'plugin' => 'CakeDC/Users', 'controller' => 'Users', - 'action' => 'resetGoogleAuthenticator', + 'action' => 'resetOneTimePasswordAuthenticator', 'allowed' => function (array $user, $role, \Cake\Http\ServerRequest $request) { $userId = \Cake\Utility\Hash::get($request->getAttribute('params'), 'pass.0'); if (!empty($userId) && !empty($user)) { diff --git a/config/routes.php b/config/routes.php index c843f94ab..1261a2c61 100644 --- a/config/routes.php +++ b/config/routes.php @@ -22,13 +22,13 @@ 'action' => 'validate' ]); // Google Authenticator related routes -if (Configure::read('Users.GoogleAuthenticator.login')) { +if (Configure::read('Users.OneTimePasswordAuthenticator.login')) { Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']); - Router::connect('/resetGoogleAuthenticator', [ + Router::connect('/resetOneTimePasswordAuthenticator', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', - 'action' => 'resetGoogleAuthenticator' + 'action' => 'resetOneTimePasswordAuthenticator' ]); } diff --git a/config/users.php b/config/users.php index 8c1c217b4..232306d05 100644 --- a/config/users.php +++ b/config/users.php @@ -58,7 +58,7 @@ // enable social login 'login' => false, ], - 'GoogleAuthenticator' => [ + 'OneTimePasswordAuthenticator' => [ // enable Google Authenticator 'login' => false, 'issuer' => null, @@ -113,7 +113,7 @@ ] ], ], - 'GoogleAuthenticator' => [ + 'OneTimePasswordAuthenticator' => [ 'verifyAction' => [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', diff --git a/src/Authentication/AuthenticationService.php b/src/Authentication/AuthenticationService.php index 38ce7517f..6e4ff46cf 100644 --- a/src/Authentication/AuthenticationService.php +++ b/src/Authentication/AuthenticationService.php @@ -56,7 +56,7 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface ); } - $googleVerify = Configure::read('Users.GoogleAuthenticator.login'); + $googleVerify = Configure::read('Users.OneTimePasswordAuthenticator.login'); $this->failures = []; $result = null; diff --git a/src/Controller/Component/GoogleAuthenticatorComponent.php b/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php similarity index 72% rename from src/Controller/Component/GoogleAuthenticatorComponent.php rename to src/Controller/Component/OneTimePasswordAuthenticatorComponent.php index 8b590e477..75a8bc620 100644 --- a/src/Controller/Component/GoogleAuthenticatorComponent.php +++ b/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php @@ -16,11 +16,11 @@ use RobThree\Auth\TwoFactorAuth; /** - * GoogleAuthenticator Component. + * OneTimePasswordAuthenticator Component. * * @link https://github.com/RobThree/TwoFactorAuth */ -class GoogleAuthenticatorComponent extends Component +class OneTimePasswordAuthenticatorComponent extends Component { /** @var \RobThree\Auth\TwoFactorAuth $tfa */ public $tfa; @@ -34,14 +34,14 @@ public function initialize(array $config) { parent::initialize($config); - if (Configure::read('Users.GoogleAuthenticator.login')) { + if (Configure::read('Users.OneTimePasswordAuthenticator.login')) { $this->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') + Configure::read('Users.OneTimePasswordAuthenticator.issuer'), + Configure::read('Users.OneTimePasswordAuthenticator.digits'), + Configure::read('Users.OneTimePasswordAuthenticator.period'), + Configure::read('Users.OneTimePasswordAuthenticator.algorithm'), + Configure::read('Users.OneTimePasswordAuthenticator.qrcodeprovider'), + Configure::read('Users.OneTimePasswordAuthenticator.rngprovider') ); } } diff --git a/src/Controller/Traits/GoogleVerifyTrait.php b/src/Controller/Traits/OneTimePasswordVerifyTrait.php similarity index 92% rename from src/Controller/Traits/GoogleVerifyTrait.php rename to src/Controller/Traits/OneTimePasswordVerifyTrait.php index b03f1db2e..0cfc021b1 100644 --- a/src/Controller/Traits/GoogleVerifyTrait.php +++ b/src/Controller/Traits/OneTimePasswordVerifyTrait.php @@ -5,7 +5,7 @@ use CakeDC\Users\Authentication\AuthenticationService; use Cake\Core\Configure; -trait GoogleVerifyTrait +trait OneTimePasswordVerifyTrait { /** * Verify for Google Authenticator @@ -32,7 +32,7 @@ public function verify() return $this->redirect($loginAction); } - $secretDataUri = $this->GoogleAuthenticator->getQRCodeImageAsDataUri( + $secretDataUri = $this->OneTimePasswordAuthenticator->getQRCodeImageAsDataUri( $temporarySession['email'], $secret ); @@ -52,7 +52,7 @@ public function verify() */ protected function isVerifyAllowed() { - if (!Configure::read('Users.GoogleAuthenticator.login')) { + if (!Configure::read('Users.OneTimePasswordAuthenticator.login')) { $message = __d('CakeDC/Users', 'Please enable Google Authenticator first.'); $this->Flash->error($message, 'default', [], 'auth'); @@ -84,7 +84,7 @@ protected function onVerifyGetSecret($user) return $user['secret']; } - $secret = $this->GoogleAuthenticator->createSecret(); + $secret = $this->OneTimePasswordAuthenticator->createSecret(); // catching sql exception in case of any sql inconsistencies try { @@ -121,7 +121,7 @@ protected function onPostVerifyCode($loginAction) $entity = $this->getUsersTable()->get($user['id']); if (!empty($entity['secret'])) { - $codeVerified = $this->GoogleAuthenticator->verifyCode($entity['secret'], $verificationCode); + $codeVerified = $this->OneTimePasswordAuthenticator->verifyCode($entity['secret'], $verificationCode); } if (!$codeVerified) { diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index fa2135e12..90087c8e7 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -151,7 +151,7 @@ public function requestResetPassword() } /** - * resetGoogleAuthenticator + * resetOneTimePasswordAuthenticator * * Resets Google Authenticator token by setting secret_verified * to false. @@ -159,7 +159,7 @@ public function requestResetPassword() * @param mixed $id of the user record. * @return mixed. */ - public function resetGoogleAuthenticator($id = null) + public function resetOneTimePasswordAuthenticator($id = null) { if ($this->request->is('post')) { try { diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 2dba7dc18..2081f4180 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -12,7 +12,7 @@ namespace CakeDC\Users\Controller; use Cake\Utility\Hash; -use CakeDC\Users\Controller\Traits\GoogleVerifyTrait; +use CakeDC\Users\Controller\Traits\OneTimePasswordVerifyTrait; use CakeDC\Users\Controller\Traits\LinkSocialTrait; use CakeDC\Users\Controller\Traits\LoginTrait; use CakeDC\Users\Controller\Traits\ProfileTrait; @@ -30,9 +30,9 @@ */ class UsersController extends AppController { - use GoogleVerifyTrait; use LinkSocialTrait; use LoginTrait; + use OneTimePasswordVerifyTrait; use ProfileTrait; use ReCaptchaTrait; use RegisterTrait; @@ -52,7 +52,7 @@ public function initialize() } /** - * Load all auth components needed: Authentication.Authentication, Authorization.Authorization and CakeDC/Users.GoogleAuthenticator + * Load all auth components needed: Authentication.Authentication, Authorization.Authorization and CakeDC/Users.OneTimePasswordAuthenticator * * @return void */ @@ -69,8 +69,8 @@ protected function loadAuthComponents() $this->loadComponent('Authorization.Authorization', $config); } - if (Configure::read('Users.GoogleAuthenticator.login') !== false) { - $this->loadComponent('CakeDC/Users.GoogleAuthenticator'); + if (Configure::read('Users.OneTimePasswordAuthenticator.login') !== false) { + $this->loadComponent('CakeDC/Users.OneTimePasswordAuthenticator'); } } } diff --git a/src/Middleware/GoogleAuthenticatorMiddleware.php b/src/Middleware/OneTimePasswordAuthenticatorMiddleware.php similarity index 96% rename from src/Middleware/GoogleAuthenticatorMiddleware.php rename to src/Middleware/OneTimePasswordAuthenticatorMiddleware.php index 9dbf0ffd0..f976a3ba1 100644 --- a/src/Middleware/GoogleAuthenticatorMiddleware.php +++ b/src/Middleware/OneTimePasswordAuthenticatorMiddleware.php @@ -7,7 +7,7 @@ use Cake\Routing\Router; use Psr\Http\Message\ResponseInterface; -class GoogleAuthenticatorMiddleware +class OneTimePasswordAuthenticatorMiddleware { /** * Proceed to second step of two factor authentication. See CakeDC\Users\Controller\Traits\verify diff --git a/src/Plugin.php b/src/Plugin.php index 967763f3e..79f365337 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -13,7 +13,7 @@ use Authorization\Policy\ResolverCollection; use CakeDC\Auth\Middleware\RbacMiddleware; use CakeDC\Users\Authentication\AuthenticationService; -use CakeDC\Users\Middleware\GoogleAuthenticatorMiddleware; +use CakeDC\Users\Middleware\OneTimePasswordAuthenticatorMiddleware; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; use CakeDC\Users\Policy\RbacPolicy; @@ -96,7 +96,7 @@ public function authentication() $service->loadAuthenticator($authenticator, $options); } - if (Configure::read('Users.GoogleAuthenticator.login')) { + if (Configure::read('Users.OneTimePasswordAuthenticator.login')) { $service->loadAuthenticator('CakeDC/Users.GoogleTwoFactor', [ 'skipGoogleVerify' => true, ]); @@ -119,8 +119,8 @@ public function middleware($middlewareQueue) $authentication = new AuthenticationMiddleware($this); $middlewareQueue->add($authentication); - if (Configure::read('Users.GoogleAuthenticator.login')) { - $middlewareQueue->add(GoogleAuthenticatorMiddleware::class); + if (Configure::read('Users.OneTimePasswordAuthenticator.login')) { + $middlewareQueue->add(OneTimePasswordAuthenticatorMiddleware::class); } $middlewareQueue = $this->addAuthorizationMiddleware($middlewareQueue); diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index 49854918d..9a3772ba5 100644 --- a/src/Template/Users/edit.ctp +++ b/src/Template/Users/edit.ctp @@ -57,14 +57,14 @@ $Users = ${$tableAlias}; 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 + 'action' => 'resetOneTimePasswordAuthenticator', $Users->id ], [ 'class' => 'btn btn-danger', 'confirm' => __d( diff --git a/tests/TestCase/Authentication/AuthenticationServiceTest.php b/tests/TestCase/Authentication/AuthenticationServiceTest.php index eb2d96e3b..575086b2b 100644 --- a/tests/TestCase/Authentication/AuthenticationServiceTest.php +++ b/tests/TestCase/Authentication/AuthenticationServiceTest.php @@ -141,7 +141,7 @@ public function testAuthenticate() */ public function testAuthenticateShouldDoGoogleVerifyEnabled() { - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $entity = $Table->get('00000000-0000-0000-0000-000000000001'); $entity->password = 'password'; @@ -194,7 +194,7 @@ public function testAuthenticateShouldDoGoogleVerifyEnabled() */ public function testAuthenticateShouldDoGoogleVerifyDisabled() { - Configure::write('Users.GoogleAuthenticator.login', false); + Configure::write('Users.OneTimePasswordAuthenticator.login', false); $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $entity = $Table->get('00000000-0000-0000-0000-000000000001'); $entity->password = 'password'; diff --git a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/OneTimePasswordAuthenticatorComponentTest.php similarity index 66% rename from tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php rename to tests/TestCase/Controller/Component/OneTimePasswordAuthenticatorComponentTest.php index 3252a6d60..39c1a38c4 100644 --- a/tests/TestCase/Controller/Component/GoogleAuthenticatorComponentTest.php +++ b/tests/TestCase/Controller/Component/OneTimePasswordAuthenticatorComponentTest.php @@ -11,14 +11,14 @@ namespace CakeDC\Users\Test\TestCase\Controller\Component; -use CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent; +use CakeDC\Users\Controller\Component\OneTimePasswordAuthenticatorComponent; use Cake\Controller\Controller; use Cake\Core\Configure; use Cake\Routing\Router; use Cake\TestSuite\TestCase; use Cake\Utility\Security; -class GoogleAuthenticatorComponentTest extends TestCase +class OneTimePasswordAuthenticatorComponentTest extends TestCase { public $fixtures = [ 'plugin.CakeDC/Users.users' @@ -48,7 +48,7 @@ public function setUp() Security::setSalt('YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); Configure::write('App.namespace', 'Users'); - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); $this->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is', 'method']) @@ -59,7 +59,7 @@ public function setUp() ->getMock(); $this->Controller = new Controller($this->request, $this->response); $this->Registry = $this->Controller->components(); - $this->Controller->GoogleAuthenticator = new GoogleAuthenticatorComponent($this->Registry); + $this->Controller->OneTimePasswordAuthenticator = new OneTimePasswordAuthenticatorComponent($this->Registry); } /** @@ -72,9 +72,9 @@ public function tearDown() parent::tearDown(); $_SESSION = []; - unset($this->Controller, $this->GoogleAuthenticator); + unset($this->Controller, $this->OneTimePasswordAuthenticator); Configure::write('Users', $this->backupUsersConfig); - Configure::write('Users.GoogleAuthenticator.login', false); + Configure::write('Users.OneTimePasswordAuthenticator.login', false); } /** @@ -83,8 +83,8 @@ public function tearDown() */ public function testInitialize() { - $this->Controller->GoogleAuthenticator = new GoogleAuthenticatorComponent($this->Registry); - $this->assertInstanceOf('CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent', $this->Controller->GoogleAuthenticator); + $this->Controller->OneTimePasswordAuthenticator = new OneTimePasswordAuthenticatorComponent($this->Registry); + $this->assertInstanceOf('CakeDC\Users\Controller\Component\OneTimePasswordAuthenticatorComponent', $this->Controller->OneTimePasswordAuthenticator); } /** @@ -93,8 +93,8 @@ public function testInitialize() */ public function testgetQRCodeImageAsDataUri() { - $this->Controller->GoogleAuthenticator->initialize([]); - $result = $this->Controller->GoogleAuthenticator->getQRCodeImageAsDataUri('test@localhost.com', '123123'); + $this->Controller->OneTimePasswordAuthenticator->initialize([]); + $result = $this->Controller->OneTimePasswordAuthenticator->getQRCodeImageAsDataUri('test@localhost.com', '123123'); $this->assertContains('data:image/png;base64', $result); } @@ -105,8 +105,8 @@ public function testgetQRCodeImageAsDataUri() */ public function testCreateSecret() { - $this->Controller->GoogleAuthenticator->initialize([]); - $result = $this->Controller->GoogleAuthenticator->createSecret(); + $this->Controller->OneTimePasswordAuthenticator->initialize([]); + $result = $this->Controller->OneTimePasswordAuthenticator->createSecret(); $this->assertNotEmpty($result); } @@ -116,11 +116,11 @@ public function testCreateSecret() */ public function testVerifyCode() { - $this->Controller->GoogleAuthenticator->initialize([]); - $secret = $this->Controller->GoogleAuthenticator->createSecret(); - $verificationCode = $this->Controller->GoogleAuthenticator->tfa->getCode($secret); + $this->Controller->OneTimePasswordAuthenticator->initialize([]); + $secret = $this->Controller->OneTimePasswordAuthenticator->createSecret(); + $verificationCode = $this->Controller->OneTimePasswordAuthenticator->tfa->getCode($secret); - $verified = $this->Controller->GoogleAuthenticator->verifyCode($secret, $verificationCode); + $verified = $this->Controller->OneTimePasswordAuthenticator->verifyCode($secret, $verificationCode); $this->assertTrue($verified); } } diff --git a/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php similarity index 84% rename from tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php rename to tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php index a1ea43118..1d8354c82 100644 --- a/tests/TestCase/Controller/Traits/GoogleVerifyTraitTest.php +++ b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php @@ -11,14 +11,14 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use CakeDC\Users\Controller\Component\GoogleAuthenticatorComponent; +use CakeDC\Users\Controller\Component\OneTimePasswordAuthenticatorComponent; use CakeDC\Users\Controller\Component\UsersAuthComponent; -use CakeDC\Users\Controller\Traits\GoogleVerify; +use CakeDC\Users\Controller\Traits\OneTimePasswordVerifyTrait; use Cake\Core\Configure; use Cake\Http\ServerRequest; use Cake\ORM\TableRegistry; -class GoogleVerifyTest extends BaseTraitTest +class OneTimePasswordVerifyTraitTest extends BaseTraitTest { protected $loginPage = '/login-page'; /** @@ -28,12 +28,12 @@ class GoogleVerifyTest extends BaseTraitTest */ public function setUp() { - $this->traitClassName = 'CakeDC\Users\Controller\Traits\GoogleVerifyTrait'; + $this->traitClassName = 'CakeDC\Users\Controller\Traits\OneTimePasswordVerifyTrait'; $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set']; parent::setUp(); $request = new ServerRequest(); - $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\GoogleVerifyTrait') + $this->Trait = $this->getMockBuilder('CakeDC\Users\Controller\Traits\OneTimePasswordVerifyTrait') ->setMethods(['dispatchEvent', 'redirect', 'set', 'getUsersTable']) ->getMockForTrait(); @@ -57,7 +57,7 @@ public function tearDown() */ public function testVerifyHappy() { - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is', 'getData', 'allow', 'getSession']) ->getMock(); @@ -85,7 +85,7 @@ public function testVerifyHappy() public function testVerifyNotEnabled() { $this->_mockFlash(); - Configure::write('Users.GoogleAuthenticator.login', false); + Configure::write('Users.OneTimePasswordAuthenticator.login', false); $this->Trait->Flash->expects($this->once()) ->method('error') ->with('Please enable Google Authenticator first.'); @@ -102,8 +102,8 @@ public function testVerifyNotEnabled() */ public function testVerifyGetShowQR() { - Configure::write('Users.GoogleAuthenticator.login', true); - $this->Trait->GoogleAuthenticator = $this->getMockBuilder(GoogleAuthenticatorComponent::class) + Configure::write('Users.OneTimePasswordAuthenticator.login', true); + $this->Trait->OneTimePasswordAuthenticator = $this->getMockBuilder(OneTimePasswordAuthenticatorComponent::class) ->disableOriginalConstructor() ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) ->getMock(); @@ -126,10 +126,10 @@ public function testVerifyGetShowQR() ->method('is') ->with('post') ->will($this->returnValue(false)); - $this->Trait->GoogleAuthenticator->expects($this->at(0)) + $this->Trait->OneTimePasswordAuthenticator->expects($this->at(0)) ->method('createSecret') ->will($this->returnValue('newSecret')); - $this->Trait->GoogleAuthenticator->expects($this->at(1)) + $this->Trait->OneTimePasswordAuthenticator->expects($this->at(1)) ->method('getQRCodeImageAsDataUri') ->with('email@example.com', 'newSecret') ->will($this->returnValue('newDataUriGenerated')); @@ -148,10 +148,10 @@ public function testVerifyGetShowQR() */ public function testVerifyGetGeneratesNewSecret() { - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); - $this->Trait->GoogleAuthenticator = $this - ->getMockBuilder(GoogleAuthenticatorComponent::class) + $this->Trait->OneTimePasswordAuthenticator = $this + ->getMockBuilder(OneTimePasswordAuthenticatorComponent::class) ->disableOriginalConstructor() ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) ->getMock(); @@ -166,11 +166,11 @@ public function testVerifyGetGeneratesNewSecret() ->with('post') ->will($this->returnValue(false)); - $this->Trait->GoogleAuthenticator + $this->Trait->OneTimePasswordAuthenticator ->expects($this->at(0)) ->method('createSecret') ->will($this->returnValue('newSecret')); - $this->Trait->GoogleAuthenticator + $this->Trait->OneTimePasswordAuthenticator ->expects($this->at(1)) ->method('getQRCodeImageAsDataUri') ->with('email@example.com', 'newSecret') @@ -207,10 +207,10 @@ public function testVerifyGetGeneratesNewSecret() */ public function testVerifyGetDoesNotGenerateNewSecret() { - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); - $this->Trait->GoogleAuthenticator = $this - ->getMockBuilder(GoogleAuthenticatorComponent::class) + $this->Trait->OneTimePasswordAuthenticator = $this + ->getMockBuilder(OneTimePasswordAuthenticatorComponent::class) ->disableOriginalConstructor() ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) ->getMock(); @@ -225,10 +225,10 @@ public function testVerifyGetDoesNotGenerateNewSecret() ->with('post') ->will($this->returnValue(false)); - $this->Trait->GoogleAuthenticator + $this->Trait->OneTimePasswordAuthenticator ->expects($this->never()) ->method('createSecret'); - $this->Trait->GoogleAuthenticator + $this->Trait->OneTimePasswordAuthenticator ->expects($this->at(0)) ->method('getQRCodeImageAsDataUri') ->with('email@example.com', 'alreadyPresentSecret') diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index a36b0c348..bc5e2178e 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -419,7 +419,7 @@ public function ensureUserActiveForResetPasswordFeature() } /** - * @dataProvider ensureGoogleAuthenticatorResets + * @dataProvider ensureOneTimePasswordAuthenticatorResets * * @return void */ @@ -443,10 +443,10 @@ public function testRequestGoogleAuthTokenResetWithValidUser($userId, $entityId, ->method($method) ->with($msg); - $this->Trait->resetGoogleAuthenticator($entityId); + $this->Trait->resetOneTimePasswordAuthenticator($entityId); } - public function ensureGoogleAuthenticatorResets() + public function ensureOneTimePasswordAuthenticatorResets() { $error = 'error'; $success = 'success'; diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 6f73c2bde..417304b28 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -15,7 +15,7 @@ use CakeDC\Users\Authentication\AuthenticationService as CakeDCAuthenticationService; use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\GoogleTwoFactorAuthenticator; -use CakeDC\Users\Middleware\GoogleAuthenticatorMiddleware; +use CakeDC\Users\Middleware\OneTimePasswordAuthenticatorMiddleware; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; use CakeDC\Users\Plugin; @@ -39,7 +39,7 @@ class PluginTest extends IntegrationTestCase public function testMiddleware() { Configure::write('Users.Social.login', true); - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); Configure::write('Auth.Authorization.loadRbacMiddleware', false); @@ -52,7 +52,7 @@ public function testMiddleware() $this->assertInstanceOf(SocialAuthMiddleware::class, $middleware->get(0)); $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); - $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(3)); + $this->assertInstanceOf(OneTimePasswordAuthenticatorMiddleware::class, $middleware->get(3)); $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(4)); $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->get(5)); $this->assertEquals(6, $middleware->count()); @@ -66,7 +66,7 @@ public function testMiddleware() public function testMiddlewareAuthorizationMiddlewareAndRbacMiddleware() { Configure::write('Users.Social.login', true); - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); Configure::write('Auth.Authorization.loadRbacMiddleware', true); @@ -79,7 +79,7 @@ public function testMiddlewareAuthorizationMiddlewareAndRbacMiddleware() $this->assertInstanceOf(SocialAuthMiddleware::class, $middleware->get(0)); $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); - $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(3)); + $this->assertInstanceOf(OneTimePasswordAuthenticatorMiddleware::class, $middleware->get(3)); $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(4)); $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->get(5)); $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(6)); @@ -94,7 +94,7 @@ public function testMiddlewareAuthorizationMiddlewareAndRbacMiddleware() public function testMiddlewareAuthorizationOnlyRbacMiddleware() { Configure::write('Users.Social.login', true); - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', false); Configure::write('Auth.Authorization.loadRbacMiddleware', true); @@ -107,7 +107,7 @@ public function testMiddlewareAuthorizationOnlyRbacMiddleware() $this->assertInstanceOf(SocialAuthMiddleware::class, $middleware->get(0)); $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); - $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(3)); + $this->assertInstanceOf(OneTimePasswordAuthenticatorMiddleware::class, $middleware->get(3)); $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(4)); $this->assertEquals(5, $middleware->count()); } @@ -120,7 +120,7 @@ public function testMiddlewareAuthorizationOnlyRbacMiddleware() public function testMiddlewareWithoutAuhorization() { Configure::write('Users.Social.login', true); - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', false); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true);//ignore Configure::write('Auth.Authorization.loadRbacMiddleware', true);//ignore @@ -133,7 +133,7 @@ public function testMiddlewareWithoutAuhorization() $this->assertInstanceOf(SocialAuthMiddleware::class, $middleware->get(0)); $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); - $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(3)); + $this->assertInstanceOf(OneTimePasswordAuthenticatorMiddleware::class, $middleware->get(3)); $this->assertEquals(4, $middleware->count()); } @@ -145,7 +145,7 @@ public function testMiddlewareWithoutAuhorization() public function testMiddlewareNotSocial() { Configure::write('Users.Social.login', false); - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); Configure::write('Auth.Authorization.loadRbacMiddleware', false); @@ -155,7 +155,7 @@ public function testMiddlewareNotSocial() $middleware = $plugin->middleware($middleware); $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(0)); - $this->assertInstanceOf(GoogleAuthenticatorMiddleware::class, $middleware->get(1)); + $this->assertInstanceOf(OneTimePasswordAuthenticatorMiddleware::class, $middleware->get(1)); $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(2)); $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->get(3)); } @@ -165,10 +165,10 @@ public function testMiddlewareNotSocial() * * @return void */ - public function testMiddlewareNotGoogleAuthenticator() + public function testMiddlewareNotOneTimePasswordAuthenticator() { Configure::write('Users.Social.login', true); - Configure::write('Users.GoogleAuthenticator.login', false); + Configure::write('Users.OneTimePasswordAuthenticator.login', false); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); Configure::write('Auth.Authorization.loadRbacMiddleware', false); @@ -192,7 +192,7 @@ public function testMiddlewareNotGoogleAuthenticator() public function testMiddlewareNotGoogleAuthenticationAndNotSocial() { Configure::write('Users.Social.login', false); - Configure::write('Users.GoogleAuthenticator.login', false); + Configure::write('Users.OneTimePasswordAuthenticator.login', false); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); Configure::write('Auth.Authorization.loadRbacMiddleware', false); @@ -243,7 +243,7 @@ public function testGetAuthenticationService() ], 'Authentication.JwtSubject' ]); - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); $plugin = new Plugin(); $service = $plugin->getAuthenticationService(new ServerRequest(), new Response()); @@ -320,7 +320,7 @@ public function testGetAuthenticationService() * * @return void */ - public function testGetAuthenticationServiceWithouGoogleAuthenticator() + public function testGetAuthenticationServiceWithouOneTimePasswordAuthenticator() { Configure::write('Auth.Authenticators', [ 'Authentication.Session' => [ @@ -347,7 +347,7 @@ public function testGetAuthenticationServiceWithouGoogleAuthenticator() ], 'Authentication.JwtSubject' ]); - Configure::write('Users.GoogleAuthenticator.login', false); + Configure::write('Users.OneTimePasswordAuthenticator.login', false); $plugin = new Plugin(); $service = $plugin->getAuthenticationService(new ServerRequest(), new Response()); diff --git a/tests/TestCase/Utility/UsersUrlTest.php b/tests/TestCase/Utility/UsersUrlTest.php index feded4784..d34e39497 100644 --- a/tests/TestCase/Utility/UsersUrlTest.php +++ b/tests/TestCase/Utility/UsersUrlTest.php @@ -43,7 +43,7 @@ public function dataProviderActionUrl() ['changePassword', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'changePassword'], null], ['resetPassword', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetPassword'], null], ['requestResetPassword', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'requestResetPassword'], null], - ['resetGoogleAuthenticator', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetGoogleAuthenticator'], null], + ['resetOneTimePasswordAuthenticator', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetOneTimePasswordAuthenticator'], null], ['validate', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validate'], null], ['resendTokenValidation', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resendTokenValidation'], null], ['index', ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'index'], null], @@ -68,7 +68,7 @@ public function dataProviderActionUrl() ['changePassword', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'changePassword'], 'Users'], ['resetPassword', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'resetPassword'], 'Users'], ['requestResetPassword', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'requestResetPassword'], 'Users'], - ['resetGoogleAuthenticator', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'resetGoogleAuthenticator'], 'Users'], + ['resetOneTimePasswordAuthenticator', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'resetOneTimePasswordAuthenticator'], 'Users'], ['validate', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'validate'], 'Users'], ['resendTokenValidation', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'resendTokenValidation'], 'Users'], ['index', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'index'], 'Users'], From ab2e67bf3c68f3f5b6e0cea6f65dedb81535078b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 15 Nov 2018 15:58:46 -0200 Subject: [PATCH 154/685] Locator was refactored into --- .../App.png | Bin .../FirstLogin.png | Bin 2 files changed, 0 insertions(+), 0 deletions(-) rename Docs/Documentation/{GoogleAuthenticator => OneTimePasswordAuthenticator}/App.png (100%) rename Docs/Documentation/{GoogleAuthenticator => OneTimePasswordAuthenticator}/FirstLogin.png (100%) diff --git a/Docs/Documentation/GoogleAuthenticator/App.png b/Docs/Documentation/OneTimePasswordAuthenticator/App.png similarity index 100% rename from Docs/Documentation/GoogleAuthenticator/App.png rename to Docs/Documentation/OneTimePasswordAuthenticator/App.png diff --git a/Docs/Documentation/GoogleAuthenticator/FirstLogin.png b/Docs/Documentation/OneTimePasswordAuthenticator/FirstLogin.png similarity index 100% rename from Docs/Documentation/GoogleAuthenticator/FirstLogin.png rename to Docs/Documentation/OneTimePasswordAuthenticator/FirstLogin.png From f126c89621090ac25d0f92c62ec1b1873b469aed Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 15 Nov 2018 16:01:34 -0200 Subject: [PATCH 155/685] Rename GoogleAuthenticator to OneTimePasswordAuthenticator --- ...-Two-Factor-Authenticator.md => Two-Factor-Authenticator.md} | 2 +- Docs/Home.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename Docs/Documentation/{Google-Two-Factor-Authenticator.md => Two-Factor-Authenticator.md} (92%) diff --git a/Docs/Documentation/Google-Two-Factor-Authenticator.md b/Docs/Documentation/Two-Factor-Authenticator.md similarity index 92% rename from Docs/Documentation/Google-Two-Factor-Authenticator.md rename to Docs/Documentation/Two-Factor-Authenticator.md index 47b128bda..de5fdcfd7 100644 --- a/Docs/Documentation/Google-Two-Factor-Authenticator.md +++ b/Docs/Documentation/Two-Factor-Authenticator.md @@ -12,7 +12,7 @@ composer require robthree/twofactorauth Setup ----- -Enable google authenticator in your bootstrap.php file: +Enable one-time password authenticator in your bootstrap.php file: Config/bootstrap.php ``` diff --git a/Docs/Home.md b/Docs/Home.md index 378d61db9..2a356f5ee 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -17,7 +17,7 @@ Documentation * [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) +* [Google Authenticator](Documentation/Two-Factor-Authenticator.md) * [UserHelper](Documentation/UserHelper.md) * [Events](Documentation/Events.md) * [Extending the Plugin](Documentation/Extending-the-Plugin.md) From 5a5e06639de6803f6b3a979f8964d1cd9257e78f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 15 Nov 2018 16:01:52 -0200 Subject: [PATCH 156/685] Rename GoogleAuthenticator to OneTimePasswordAuthenticator --- Docs/Documentation/Two-Factor-Authenticator.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Two-Factor-Authenticator.md b/Docs/Documentation/Two-Factor-Authenticator.md index de5fdcfd7..30464cdc1 100644 --- a/Docs/Documentation/Two-Factor-Authenticator.md +++ b/Docs/Documentation/Two-Factor-Authenticator.md @@ -1,4 +1,4 @@ -Google Two Factor Authenticator +Two Factor Authenticator =============================== Installation From 8d7bb4de83d73219f452e89dc3b946a4a7a6eb46 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 15 Nov 2018 16:32:57 -0200 Subject: [PATCH 157/685] Document config key loadAuthorizationMiddleware and loadRbacMiddleware --- Docs/Documentation/Configuration.md | 17 +++++++++++++++++ src/Plugin.php | 1 - 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index f52015acb..e3a2bae56 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -145,6 +145,23 @@ Using the UsersAuthComponent default initialization, the component will load the * '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 +Default Authorization Behavior +------------------------------ +For authorization process this plugin loads two cakephp/authorization midlewares, +**AuthorizationMiddleware** and **RequestAuthorizationMiddleware** (used with **RbacPolicy**). + +#### Configure AuthorizationMiddleware + +You can configure AuthorizationMiddleware by setting 'Auth.AuthorizationMiddleware' config, +check available options at https://github.com/cakephp/authorization/blob/master/docs/Middleware.md + +#### Additional configurations + +* **Auth.Authorization.enable:** defaults to true, enable authorization and try to load needed middlewares +* **Auth.Authorization.loadAuthorizationMiddleware:** defaults to true, load AuthorizationMiddleware and RequestAuthorizationMiddleware (used with RbacPolicy) +* **Auth.Authorization.loadRbacMiddleware:** defaults to false, if you don't want to use cakephp/authorization but want to +use Rbac permissions, set this config to true. + ## Using the user's email to login You need to configure 2 things: diff --git a/src/Plugin.php b/src/Plugin.php index 79f365337..7c4e7b2f9 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -141,7 +141,6 @@ protected function addAuthorizationMiddleware(MiddlewareQueue $middlewareQueue) } if (Configure::read('Auth.Authorization.loadAuthorizationMiddleware') !== false) { - $config = Configure::read('Auth.AuthorizationMiddleware'); $middlewareQueue->add(new AuthorizationMiddleware($this, Configure::read('Auth.AuthorizationMiddleware'))); $middlewareQueue->add(new RequestAuthorizationMiddleware()); } From 4fdeec423f71a2aa2666800d974f0bf79545f0d3 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 15 Nov 2018 16:55:21 -0200 Subject: [PATCH 158/685] documented how to add logic before login with middleware at migration guide --- Docs/Documentation/InterceptLoginAction.md | 48 ++++++++++++++++++++++ Docs/Home.md | 1 + 2 files changed, 49 insertions(+) create mode 100644 Docs/Documentation/InterceptLoginAction.md diff --git a/Docs/Documentation/InterceptLoginAction.md b/Docs/Documentation/InterceptLoginAction.md new file mode 100644 index 000000000..a4bc96336 --- /dev/null +++ b/Docs/Documentation/InterceptLoginAction.md @@ -0,0 +1,48 @@ +Intercept Login Action +====================== + +There is a moment when you may want to intercept the login action to perform +some specific login, like redirect user to another url or set user data. +A simple way to intercept the login action is by creating a custom middleware, the following +example shows how to set user data and redirect to anothe url. + +``` +checkActionOnRequest('login', $request)) { + return $next($request, $response); + } + + if (!$request->getAttribute('session')->read('Auth')) { + //do some logic + //do more logic + $request->getAttribute('session')->write('Auth', $userIdentity); + + $response = $response->withHeader('Location', '/pages/33'); + + return $response; + } + + return $next($request, $response); + } + +} +``` + diff --git a/Docs/Home.md b/Docs/Home.md index 2a356f5ee..a3b35a60c 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -16,6 +16,7 @@ Documentation * [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) +* [Intercept Login Action](Documentation/InterceptLoginAction.md) * [SocialAuthenticate](Documentation/SocialAuthenticate.md) * [Google Authenticator](Documentation/Two-Factor-Authenticator.md) * [UserHelper](Documentation/UserHelper.md) From e484a83ac8da5138b3efce6d75dcb3a9d005738a Mon Sep 17 00:00:00 2001 From: Fahad Alrahbi Date: Fri, 16 Nov 2018 01:19:06 +0400 Subject: [PATCH 159/685] Add defualt user role if logged by using social networks --- src/Model/Behavior/SocialBehavior.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 7fdd2c0f0..683fd03a2 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -21,7 +21,7 @@ use Cake\Utility\Hash; use DateTime; use InvalidArgumentException; - +use Cake\Core\Configure; /** * Covers social features * @@ -229,7 +229,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail //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; } From ea0c3276c996b74267a3c52427999eb4e7dc2226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 16 Nov 2018 09:56:46 +0000 Subject: [PATCH 160/685] fix cs --- src/Model/Behavior/SocialBehavior.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 683fd03a2..506da4c96 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -16,12 +16,13 @@ use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Traits\RandomStringTrait; +use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Event\EventDispatcherTrait; use Cake\Utility\Hash; use DateTime; use InvalidArgumentException; -use Cake\Core\Configure; + /** * Covers social features * @@ -230,6 +231,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $socialAccount['provider'] = Hash::get($data, 'provider'); $user['social_accounts'] = [$socialAccount]; $user['role'] = Configure::read('Users.Registration.defaultRole') ?: 'user'; + return $user; } From 548ff450410fb8e55900421d400238f19f4a7da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 16 Nov 2018 10:08:04 +0000 Subject: [PATCH 161/685] fix cs From 1498b1ccb523b4224dfad9712fb51012b8c6f5a9 Mon Sep 17 00:00:00 2001 From: Fahad Alrahbi Date: Fri, 16 Nov 2018 15:31:08 +0400 Subject: [PATCH 162/685] fix whitespace --- src/Model/Behavior/SocialBehavior.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 506da4c96..b93c01c4f 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -16,12 +16,12 @@ use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Traits\RandomStringTrait; -use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Event\EventDispatcherTrait; use Cake\Utility\Hash; use DateTime; use InvalidArgumentException; +use Cake\Core\Configure; /** * Covers social features @@ -231,7 +231,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $socialAccount['provider'] = Hash::get($data, 'provider'); $user['social_accounts'] = [$socialAccount]; $user['role'] = Configure::read('Users.Registration.defaultRole') ?: 'user'; - + return $user; } From 92f79706b46529e1bc5143f4c551f16334f49991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 16 Nov 2018 11:38:37 +0000 Subject: [PATCH 163/685] fix import order to make phpcs happy --- src/Model/Behavior/SocialBehavior.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index b93c01c4f..8fbc82416 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -16,12 +16,12 @@ use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Traits\RandomStringTrait; +use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Event\EventDispatcherTrait; use Cake\Utility\Hash; use DateTime; use InvalidArgumentException; -use Cake\Core\Configure; /** * Covers social features From d1b6ef575d2607024c068102b8f5b1d5dae121ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 16 Nov 2018 11:44:39 +0000 Subject: [PATCH 164/685] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index fd30894e0..af406a57b 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 8 :minor: 0 -:patch: 1 +:patch: 2 :special: '' From 23a9689594e7070a424c542bad263e07e98a3355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 16 Nov 2018 11:45:21 +0000 Subject: [PATCH 165/685] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fc599209..7ba444c97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ 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 From b23bf090aa7f2652a7113097cdf85acee3b70d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 16 Nov 2018 11:45:57 +0000 Subject: [PATCH 166/685] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dac5934c8..cc71ac418 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| ^3.6 | [master](https://github.com/cakedc/users/tree/master) | 8.0.1 | stable | +| ^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 | From 07fe07d37fa85335f70c1cfdf5bb64e17aafc641 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 16 Nov 2018 16:36:05 -0200 Subject: [PATCH 167/685] Merged from develop --- src/Controller/Traits/UserValidationTrait.php | 6 +++--- src/Plugin.php | 3 +++ tests/TestCase/Controller/Traits/LoginTraitTest.php | 1 - .../Controller/Traits/OneTimePasswordVerifyTraitTest.php | 1 - 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 1b920f23f..6df82cbf3 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -11,12 +11,12 @@ namespace CakeDC\Users\Controller\Traits; -use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Exception\TokenExpiredException; use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotFoundException; use Cake\Core\Configure; use Cake\Http\Response; +use CakeDC\Users\Plugin; use Exception; /** @@ -69,7 +69,7 @@ public function validate($type = null, $token = null) } 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]); + $event = $this->dispatchEvent(Plugin::EVENT_ON_EXPIRED_TOKEN, ['type' => $type]); if (!empty($event) && is_array($event->result)) { return $this->redirect($event->result); } @@ -99,7 +99,7 @@ public function resendTokenValidation() 'sendEmail' => true, 'type' => 'email' ])) { - $event = $this->dispatchEvent(UsersAuthComponent::EVENT_AFTER_RESEND_TOKEN_VALIDATION); + $event = $this->dispatchEvent(Plugin::EVENT_AFTER_RESEND_TOKEN_VALIDATION); if (!empty($event) && is_array($event->result)) { return $this->redirect($event->result); } diff --git a/src/Plugin.php b/src/Plugin.php index 7c4e7b2f9..2d75af64f 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -36,6 +36,9 @@ class Plugin extends BasePlugin implements AuthenticationServiceProviderInterfac const EVENT_AFTER_REGISTER = 'Users.Managment.afterRegister'; const EVENT_AFTER_CHANGE_PASSWORD = 'Users.Managment.afterResetPassword'; const EVENT_BEFORE_SOCIAL_LOGIN_USER_CREATE = 'Users.Managment.beforeSocialLoginUserCreate'; + const EVENT_ON_EXPIRED_TOKEN = 'Users.Managment.onExpiredToken'; + const EVENT_AFTER_RESEND_TOKEN_VALIDATION = 'Users.Managment.afterResendTokenValidation'; + /** * Returns an authentication service instance. diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 0fd83a997..06282206e 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -20,7 +20,6 @@ use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Controller\Component\LoginComponent; -use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Middleware\SocialAuthMiddleware; use Cake\Event\Event; use Cake\Http\ServerRequest; diff --git a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php index 1d8354c82..a085bed3c 100644 --- a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php +++ b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php @@ -12,7 +12,6 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use CakeDC\Users\Controller\Component\OneTimePasswordAuthenticatorComponent; -use CakeDC\Users\Controller\Component\UsersAuthComponent; use CakeDC\Users\Controller\Traits\OneTimePasswordVerifyTrait; use Cake\Core\Configure; use Cake\Http\ServerRequest; From 766d7adba81b2f5a2f859bae37b90bd82c3339e2 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 16 Nov 2018 16:41:02 -0200 Subject: [PATCH 168/685] Mapper custom functions have $rawData as argument --- src/Social/Mapper/Facebook.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Social/Mapper/Facebook.php b/src/Social/Mapper/Facebook.php index d34ecf554..caf6caf90 100644 --- a/src/Social/Mapper/Facebook.php +++ b/src/Social/Mapper/Facebook.php @@ -46,10 +46,14 @@ protected function _avatar($rawData) } /** + * Get link property value + * + * @param mixed $rawData raw data + * * @return string */ - protected function _link() + protected function _link($rawData) { - return Hash::get($this->_rawData, 'link') ?: '#'; + return Hash::get($rawData, 'link') ?: '#'; } } From c0fb167f2691ef1eafb2e11e3994305f47665649 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 16 Nov 2018 16:46:48 -0200 Subject: [PATCH 169/685] Social mapper should be at Social namespace --- src/{Auth => }/Social/Mapper/Pinterest.php | 6 +++--- src/{Auth => }/Social/Mapper/Tumblr.php | 16 +++++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) rename src/{Auth => }/Social/Mapper/Pinterest.php (72%) rename src/{Auth => }/Social/Mapper/Tumblr.php (71%) diff --git a/src/Auth/Social/Mapper/Pinterest.php b/src/Social/Mapper/Pinterest.php similarity index 72% rename from src/Auth/Social/Mapper/Pinterest.php rename to src/Social/Mapper/Pinterest.php index d1b630b73..d3206d64e 100644 --- a/src/Auth/Social/Mapper/Pinterest.php +++ b/src/Social/Mapper/Pinterest.php @@ -1,15 +1,15 @@ _rawData['nickname']); + return crc32($rawData['nickname']); } } From 922444b9d626345560c4642bf333c8804bd9a317 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 16 Nov 2018 16:49:12 -0200 Subject: [PATCH 170/685] Fixed configuration for OneTimePasswordAuthenticator --- src/Auth/DefaultTwoFactorAuthenticationChecker.php | 2 +- src/Auth/TwoFactorAuthenticationCheckerFactory.php | 4 ++-- .../DefaultTwoFactorAuthenticationCheckerTest.php | 12 ++++++------ .../TwoFactorAuthenticationCheckerFactoryTest.php | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Auth/DefaultTwoFactorAuthenticationChecker.php b/src/Auth/DefaultTwoFactorAuthenticationChecker.php index be0c1843f..6b58ee51a 100644 --- a/src/Auth/DefaultTwoFactorAuthenticationChecker.php +++ b/src/Auth/DefaultTwoFactorAuthenticationChecker.php @@ -27,7 +27,7 @@ class DefaultTwoFactorAuthenticationChecker implements TwoFactorAuthenticationCh */ public function isEnabled() { - return Configure::read('Users.GoogleAuthenticator.login') !== false; + return Configure::read('Users.OneTimePasswordAuthenticator.login') !== false; } /** diff --git a/src/Auth/TwoFactorAuthenticationCheckerFactory.php b/src/Auth/TwoFactorAuthenticationCheckerFactory.php index 8287fdf1d..da62927b3 100644 --- a/src/Auth/TwoFactorAuthenticationCheckerFactory.php +++ b/src/Auth/TwoFactorAuthenticationCheckerFactory.php @@ -27,13 +27,13 @@ class TwoFactorAuthenticationCheckerFactory */ public function build() { - $className = Configure::read('GoogleAuthenticator.checker'); + $className = Configure::read('OneTimePasswordAuthenticator.checker'); $interfaces = class_implements($className); $required = TwoFactorAuthenticationCheckerInterface::class; if (in_array($required, $interfaces)) { return new $className(); } - throw new \InvalidArgumentException("Invalid config for 'GoogleAuthenticator.checker', '$className' does not implement '$required'"); + throw new \InvalidArgumentException("Invalid config for 'OneTimePasswordAuthenticator.checker', '$className' does not implement '$required'"); } } diff --git a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php index 6f6be7d8c..a9cb270cf 100644 --- a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php +++ b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php @@ -29,15 +29,15 @@ class DefaultTwoFactorAuthenticationCheckerTest extends TestCase */ public function testIsEnabled() { - Configure::write('Users.GoogleAuthenticator.login', false); + Configure::write('Users.OneTimePasswordAuthenticator.login', false); $Checker = new DefaultTwoFactorAuthenticationChecker(); $this->assertFalse($Checker->isEnabled()); - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); $Checker = new DefaultTwoFactorAuthenticationChecker(); $this->assertTrue($Checker->isEnabled()); - Configure::delete('Users.GoogleAuthenticator.login'); + Configure::delete('Users.OneTimePasswordAuthenticator.login'); $Checker = new DefaultTwoFactorAuthenticationChecker(); $this->assertTrue($Checker->isEnabled()); } @@ -49,15 +49,15 @@ public function testIsEnabled() */ public function testIsRequired() { - Configure::write('Users.GoogleAuthenticator.login', false); + Configure::write('Users.OneTimePasswordAuthenticator.login', false); $Checker = new DefaultTwoFactorAuthenticationChecker(); $this->assertFalse($Checker->isRequired(['id' => 10])); - Configure::write('Users.GoogleAuthenticator.login', true); + Configure::write('Users.OneTimePasswordAuthenticator.login', true); $Checker = new DefaultTwoFactorAuthenticationChecker(); $this->assertTrue($Checker->isRequired(['id' => 10])); - Configure::delete('Users.GoogleAuthenticator.login'); + Configure::delete('Users.OneTimePasswordAuthenticator.login'); $Checker = new DefaultTwoFactorAuthenticationChecker(); $this->assertTrue($Checker->isRequired(['id' => 10])); diff --git a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php index 4c4908028..17c612f31 100644 --- a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php +++ b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php @@ -36,9 +36,9 @@ public function testGetChecker() */ public function testGetCheckerInvalidInterface() { - Configure::write('GoogleAuthenticator.checker', 'stdClass'); + Configure::write('OneTimePasswordAuthenticator.checker', 'stdClass'); $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage("Invalid config for 'GoogleAuthenticator.checker', 'stdClass' does not implement 'CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface'"); + $this->expectExceptionMessage("Invalid config for 'OneTimePasswordAuthenticator.checker', 'stdClass' does not implement 'CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface'"); $result = (new TwoFactorAuthenticationCheckerFactory())->build(); } } From b77599e46f6fb6946165a154fce1c3fce8a73ba7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 16 Nov 2018 17:02:58 -0200 Subject: [PATCH 171/685] Usding 2fa checker on authetication service --- src/Authentication/AuthenticationService.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/Authentication/AuthenticationService.php b/src/Authentication/AuthenticationService.php index 6e4ff46cf..a3883127d 100644 --- a/src/Authentication/AuthenticationService.php +++ b/src/Authentication/AuthenticationService.php @@ -6,7 +6,7 @@ use Authentication\Authenticator\Result; use Authentication\Authenticator\ResultInterface; use Authentication\Authenticator\StatelessInterface; -use Cake\Core\Configure; +use CakeDC\Users\Auth\TwoFactorAuthenticationCheckerFactory; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use RuntimeException; @@ -43,6 +43,16 @@ protected function proceedToGoogleVerify(ServerRequestInterface $request, Respon return compact('result', 'request', 'response'); } + /** + * Get the configured two factory authentication + * + * @return \CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface + */ + protected function getTwoFactorAuthenticationChecker() + { + return (new TwoFactorAuthenticationCheckerFactory())->build(); + } + /** * {@inheritDoc} * @@ -56,15 +66,15 @@ public function authenticate(ServerRequestInterface $request, ResponseInterface ); } - $googleVerify = Configure::read('Users.OneTimePasswordAuthenticator.login'); - + $twoFaCheck = $this->getTwoFactorAuthenticationChecker(); $this->failures = []; $result = null; foreach ($this->authenticators() as $authenticator) { $result = $authenticator->authenticate($request, $response); if ($result->isValid()) { - if ($googleVerify !== false && $authenticator->getConfig('skipGoogleVerify') !== true) { + $twoFaRequired = $twoFaCheck->isRequired($result->getData()->toArray()); + if ($twoFaRequired && $authenticator->getConfig('skipGoogleVerify') !== true) { return $this->proceedToGoogleVerify($request, $response, $result); } From 4d1a072e200ba0503fe238bd7f3a97574944c6be Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 16 Nov 2018 17:20:24 -0200 Subject: [PATCH 172/685] Making sure 2fa redirect preserve query string from login action --- src/Controller/Traits/OneTimePasswordVerifyTrait.php | 7 ++++++- .../Traits/OneTimePasswordVerifyTraitTest.php | 12 ++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Controller/Traits/OneTimePasswordVerifyTrait.php b/src/Controller/Traits/OneTimePasswordVerifyTrait.php index 0cfc021b1..8ba57d8d0 100644 --- a/src/Controller/Traits/OneTimePasswordVerifyTrait.php +++ b/src/Controller/Traits/OneTimePasswordVerifyTrait.php @@ -18,7 +18,12 @@ trait OneTimePasswordVerifyTrait */ public function verify() { - $loginAction = Configure::read('Auth.AuthenticationComponent.loginAction'); + $loginAction = array_merge( + Configure::read('Auth.AuthenticationComponent.loginAction'), + [ + '?' => $this->request->getQueryParams() + ] + ); if (!$this->isVerifyAllowed()) { return $this->redirect($loginAction); } diff --git a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php index a085bed3c..bd81405f0 100644 --- a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php +++ b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use CakeDC\Users\Controller\Component\OneTimePasswordAuthenticatorComponent; + use CakeDC\Users\Controller\Traits\OneTimePasswordVerifyTrait; use Cake\Core\Configure; use Cake\Http\ServerRequest; @@ -19,7 +20,13 @@ class OneTimePasswordVerifyTraitTest extends BaseTraitTest { - protected $loginPage = '/login-page'; + protected $loginPage = [ + 'plugin' => 'CakeDC/Users', + 'prefix' => false, + 'controller' => 'users', + 'action' => 'login' + ]; + /** * setup * @@ -85,12 +92,13 @@ public function testVerifyNotEnabled() { $this->_mockFlash(); Configure::write('Users.OneTimePasswordAuthenticator.login', false); + $this->Trait->request = $this->Trait->request->withQueryParams(['redirect' => 'dashboard/list']); $this->Trait->Flash->expects($this->once()) ->method('error') ->with('Please enable Google Authenticator first.'); $this->Trait->expects($this->once()) ->method('redirect') - ->with($this->loginPage); + ->with($this->loginPage + ['?' => ['redirect' => 'dashboard/list']]); $this->Trait->verify(); } From c70738e97fcc49fe91f1d497ee53d355e672f73f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 16 Nov 2018 17:44:03 -0200 Subject: [PATCH 173/685] phpcs fixes --- src/Authentication/FailureInterface.php | 2 +- src/Authenticator/SocialAuthTrait.php | 9 +++------ src/Authenticator/SocialAuthenticator.php | 16 ++++++++-------- .../SocialPendingEmailAuthenticator.php | 2 +- src/Controller/Component/LoginComponent.php | 6 +++--- src/Controller/Traits/SocialTrait.php | 2 +- src/Controller/Traits/UserValidationTrait.php | 2 +- src/Controller/UsersController.php | 4 ++-- src/Exception/SocialAuthenticationException.php | 2 +- src/Middleware/SocialAuthMiddleware.php | 2 +- src/Middleware/SocialEmailMiddleware.php | 2 +- src/Plugin.php | 1 - src/Utility/UsersUrl.php | 4 ++-- .../Authenticator/SocialAuthenticatorTest.php | 10 +++++----- .../Controller/Traits/LoginTraitTest.php | 5 +++-- .../Controller/Traits/SocialTraitTest.php | 4 ++-- .../Middleware/SocialAuthMiddlewareTest.php | 11 ++++------- tests/TestCase/Utility/UsersUrlTest.php | 2 +- 18 files changed, 40 insertions(+), 46 deletions(-) diff --git a/src/Authentication/FailureInterface.php b/src/Authentication/FailureInterface.php index d4a80c3ca..1edad8d9b 100644 --- a/src/Authentication/FailureInterface.php +++ b/src/Authentication/FailureInterface.php @@ -28,4 +28,4 @@ public function getAuthenticator(); * @return \Authentication\Authenticator\ResultInterface */ public function getResult(); -} \ No newline at end of file +} diff --git a/src/Authenticator/SocialAuthTrait.php b/src/Authenticator/SocialAuthTrait.php index 14303078c..55a7778c4 100644 --- a/src/Authenticator/SocialAuthTrait.php +++ b/src/Authenticator/SocialAuthTrait.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Authenticator; - use Authentication\Authenticator\Result; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; @@ -35,14 +34,12 @@ protected function identify($rawData) } return new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND); - - } catch(AccountNotActiveException $e) { + } catch (AccountNotActiveException $e) { return new Result(null, self::FAILURE_ACCOUNT_NOT_ACTIVE); - } catch(UserNotActiveException $e) { + } catch (UserNotActiveException $e) { return new Result(null, self::FAILURE_USER_NOT_ACTIVE); } catch (MissingEmailException $exception) { throw new SocialAuthenticationException(compact('rawData'), null, $exception); } } - -} \ No newline at end of file +} diff --git a/src/Authenticator/SocialAuthenticator.php b/src/Authenticator/SocialAuthenticator.php index 320d239ea..8a373c411 100644 --- a/src/Authenticator/SocialAuthenticator.php +++ b/src/Authenticator/SocialAuthenticator.php @@ -5,17 +5,18 @@ use Authentication\Authenticator\AbstractAuthenticator; use Authentication\Authenticator\Result; use Authentication\UrlChecker\UrlCheckerTrait; -use Cake\Datasource\Exception\RecordNotFoundException; -use Cake\Http\Exception\BadRequestException; -use Cake\Log\LogTrait; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\SocialAuthenticationException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Social\MapUser; use CakeDC\Users\Social\Service\ServiceInterface; +use Cake\Datasource\Exception\RecordNotFoundException; +use Cake\Http\Exception\BadRequestException; +use Cake\Log\LogTrait; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; + /** * Social authenticator * @@ -54,8 +55,8 @@ class SocialAuthenticator extends AbstractAuthenticator * @return \Authentication\Authenticator\ResultInterface */ /** - * @param ServerRequestInterface $request - * @param ResponseInterface $response + * @param ServerRequestInterface $request the cake request. + * @param ResponseInterface $response the cake response. * @return Result|\Authentication\Authenticator\ResultInterface * @throws \Exception */ @@ -90,7 +91,7 @@ private function getRawData(ServerRequestInterface $request, ServiceInterface $s return (new MapUser())($service, $rawData); } catch (\Exception $exception) { - $list = [BadRequestException::class, \UnexpectedValueException::class]; + $list = [BadRequestException::class, \UnexpectedValueException::class]; $this->throwIfNotInlist($exception, $list); $message = sprintf( "Error getting an access token / retrieving the authorized user's profile data. Error message: %s %s", @@ -100,7 +101,6 @@ private function getRawData(ServerRequestInterface $request, ServiceInterface $s $this->log($message); return null; - } } @@ -108,7 +108,7 @@ private function getRawData(ServerRequestInterface $request, ServiceInterface $s * Throw the exception if not in the list * * @param \Exception $exception exception thrown - * @param array $allowed list of allowed exception classes + * @param array $list list of allowed exception classes * @throws \Exception * @return void */ diff --git a/src/Authenticator/SocialPendingEmailAuthenticator.php b/src/Authenticator/SocialPendingEmailAuthenticator.php index b28b62ae6..c94b2b655 100644 --- a/src/Authenticator/SocialPendingEmailAuthenticator.php +++ b/src/Authenticator/SocialPendingEmailAuthenticator.php @@ -14,9 +14,9 @@ use Authentication\Authenticator\AbstractAuthenticator; use Authentication\Authenticator\Result; use Authentication\UrlChecker\UrlCheckerTrait; +use CakeDC\Users\Controller\Traits\ReCaptchaTrait; use Cake\Core\Configure; use Cake\Utility\Hash; -use CakeDC\Users\Controller\Traits\ReCaptchaTrait; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index f6bd413fe..032c7bf17 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -2,9 +2,9 @@ namespace CakeDC\Users\Controller\Component; use Authentication\Authenticator\ResultInterface; -use Cake\Controller\Component; use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Plugin; +use Cake\Controller\Component; /** * LoginFailure component @@ -26,7 +26,7 @@ class LoginComponent extends Component /** * Handle login, if success redirect to 'AuthenticationComponent.loginRedirect' or show error * - * @param bool $failureOnlyPost should handle failure only on post request + * @param bool $errorOnlyPost should handle failure only on post request * @param bool $redirectFailure should redirect on failure? * @return \Cake\Http\Response|null */ @@ -47,7 +47,7 @@ public function handleLogin($errorOnlyPost, $redirectFailure) /** * Handle login failure * - * @param boolean $redirect should redirect? + * @param bool $redirect should redirect? * * @return \Cake\Http\Response|null */ diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index 36cc31aff..dfc1d540f 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Controller\Traits; -use Cake\Core\Configure; use CakeDC\Users\Middleware\SocialAuthMiddleware; +use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; /** diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 6df82cbf3..e2155806c 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -14,9 +14,9 @@ use CakeDC\Users\Exception\TokenExpiredException; use CakeDC\Users\Exception\UserAlreadyActiveException; use CakeDC\Users\Exception\UserNotFoundException; +use CakeDC\Users\Plugin; use Cake\Core\Configure; use Cake\Http\Response; -use CakeDC\Users\Plugin; use Exception; /** diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 2081f4180..6c1915718 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -11,10 +11,9 @@ namespace CakeDC\Users\Controller; -use Cake\Utility\Hash; -use CakeDC\Users\Controller\Traits\OneTimePasswordVerifyTrait; use CakeDC\Users\Controller\Traits\LinkSocialTrait; use CakeDC\Users\Controller\Traits\LoginTrait; +use CakeDC\Users\Controller\Traits\OneTimePasswordVerifyTrait; use CakeDC\Users\Controller\Traits\ProfileTrait; use CakeDC\Users\Controller\Traits\ReCaptchaTrait; use CakeDC\Users\Controller\Traits\RegisterTrait; @@ -22,6 +21,7 @@ use CakeDC\Users\Controller\Traits\SocialTrait; use CakeDC\Users\Model\Table\UsersTable; use Cake\Core\Configure; +use Cake\Utility\Hash; /** * Users Controller diff --git a/src/Exception/SocialAuthenticationException.php b/src/Exception/SocialAuthenticationException.php index 45341f479..7026a3e83 100644 --- a/src/Exception/SocialAuthenticationException.php +++ b/src/Exception/SocialAuthenticationException.php @@ -16,4 +16,4 @@ class SocialAuthenticationException extends Exception { protected $_messageTemplate = 'Could not autheticate user'; protected $_defaultCode = 400; -} \ No newline at end of file +} diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 4ac5c0163..f8c1251e6 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -6,11 +6,11 @@ use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\SocialAuthenticationException; use CakeDC\Users\Social\Service\ServiceFactory; +use CakeDC\Users\Utility\UsersUrl; use Cake\Core\Configure; use Cake\Http\ServerRequest; use Cake\Log\LogTrait; use Cake\Routing\Router; -use CakeDC\Users\Utility\UsersUrl; use Psr\Http\Message\ResponseInterface; class SocialAuthMiddleware diff --git a/src/Middleware/SocialEmailMiddleware.php b/src/Middleware/SocialEmailMiddleware.php index 3918a6741..6b7adfbf7 100644 --- a/src/Middleware/SocialEmailMiddleware.php +++ b/src/Middleware/SocialEmailMiddleware.php @@ -2,10 +2,10 @@ namespace CakeDC\Users\Middleware; +use CakeDC\Users\Utility\UsersUrl; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; use Cake\Http\ServerRequest; -use CakeDC\Users\Utility\UsersUrl; use Psr\Http\Message\ResponseInterface; class SocialEmailMiddleware extends SocialAuthMiddleware diff --git a/src/Plugin.php b/src/Plugin.php index 2d75af64f..deecf90cf 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -39,7 +39,6 @@ class Plugin extends BasePlugin implements AuthenticationServiceProviderInterfac const EVENT_ON_EXPIRED_TOKEN = 'Users.Managment.onExpiredToken'; const EVENT_AFTER_RESEND_TOKEN_VALIDATION = 'Users.Managment.afterResendTokenValidation'; - /** * Returns an authentication service instance. * diff --git a/src/Utility/UsersUrl.php b/src/Utility/UsersUrl.php index ce80e7997..f9a74de0c 100644 --- a/src/Utility/UsersUrl.php +++ b/src/Utility/UsersUrl.php @@ -32,7 +32,7 @@ public function actionUrl($action, $extra = []) list($plugin, $controller) = pluginSplit($controller); $plugin = $plugin ? $plugin : false; - return compact('prefix','plugin', 'controller', 'action') + $extra; + return compact('prefix', 'plugin', 'controller', 'action') + $extra; } /** @@ -54,4 +54,4 @@ public function checkActionOnRequest($action, ServerRequest $request) return true; } -} \ No newline at end of file +} diff --git a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php index 9b4397d40..9af7744f2 100644 --- a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php @@ -12,10 +12,6 @@ use Authentication\Authenticator\Result; use Authentication\Identifier\IdentifierCollection; -use Cake\Core\Configure; -use Cake\Http\Response; -use Cake\Http\ServerRequestFactory; -use Cake\TestSuite\TestCase; use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; @@ -26,6 +22,10 @@ use CakeDC\Users\Social\MapUser; use CakeDC\Users\Social\Service\OAuth2Service; use CakeDC\Users\Social\Service\ServiceFactory; +use Cake\Core\Configure; +use Cake\Http\Response; +use Cake\Http\ServerRequestFactory; +use Cake\TestSuite\TestCase; use League\OAuth2\Client\Provider\FacebookUser; use Zend\Diactoros\Uri; @@ -639,4 +639,4 @@ public function testAuthenticateErrorException($exception, $status) $actual = $result->getData(); $this->assertEmpty($actual); } -} \ No newline at end of file +} diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 06282206e..d3204dfc4 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -14,14 +14,14 @@ use Authentication\Authenticator\Result; use Authentication\Authenticator\SessionAuthenticator; use Authentication\Identifier\IdentifierCollection; -use Cake\Controller\ComponentRegistry; -use Cake\Http\Response; use CakeDC\Users\Authentication\Failure; use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Controller\Component\LoginComponent; use CakeDC\Users\Middleware\SocialAuthMiddleware; +use Cake\Controller\ComponentRegistry; use Cake\Event\Event; +use Cake\Http\Response; use Cake\Http\ServerRequest; class LoginTraitTest extends BaseTraitTest @@ -241,6 +241,7 @@ public function dataProviderLogin() ], 'targetAuthenticator' => FormAuthenticator::class ]; + return [ [ SocialAuthenticator::class, diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index faf3eb675..e671e8601 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -14,13 +14,13 @@ use Authentication\Authenticator\Result; use Authentication\Authenticator\SessionAuthenticator; use Authentication\Identifier\IdentifierCollection; -use Cake\Controller\ComponentRegistry; -use Cake\Event\Event; use CakeDC\Users\Authentication\Failure; use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Controller\Component\LoginComponent; use CakeDC\Users\Middleware\SocialAuthMiddleware; +use Cake\Controller\ComponentRegistry; +use Cake\Event\Event; use Cake\Http\Response; use Cake\Http\ServerRequest; diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index 244a6db5f..21e7112d0 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -8,20 +8,17 @@ namespace CakeDC\Users\Test\TestCase\Middleware; -use Cake\Http\ServerRequest; -use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\SocialAuthenticationException; -use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Middleware\SocialAuthMiddleware; -use CakeDC\Users\Model\Entity\User; +use CakeDC\Users\Social\MapUser; +use CakeDC\Users\Social\Service\OAuth2Service; +use CakeDC\Users\Social\Service\ServiceFactory; use Cake\Core\Configure; use Cake\Http\Response; +use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; -use CakeDC\Users\Social\MapUser; -use CakeDC\Users\Social\Service\OAuth2Service; -use CakeDC\Users\Social\Service\ServiceFactory; use Doctrine\Instantiator\Exception\UnexpectedValueException; use League\OAuth2\Client\Provider\FacebookUser; use Zend\Diactoros\Uri; diff --git a/tests/TestCase/Utility/UsersUrlTest.php b/tests/TestCase/Utility/UsersUrlTest.php index d34e39497..2a47445d9 100644 --- a/tests/TestCase/Utility/UsersUrlTest.php +++ b/tests/TestCase/Utility/UsersUrlTest.php @@ -11,10 +11,10 @@ namespace CakeDC\Users\Test\TestCase\Utility; +use CakeDC\Users\Utility\UsersUrl; use Cake\Core\Configure; use Cake\Http\ServerRequestFactory; use Cake\TestSuite\TestCase; -use CakeDC\Users\Utility\UsersUrl; use Zend\Diactoros\Uri; class UsersUrlTest extends TestCase From 2c600ad7d062e3b2a15cbb02b13acbbffd3ec800 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 16 Nov 2018 17:54:16 -0200 Subject: [PATCH 174/685] Removed ununsed import and params --- .../DefaultTwoFactorAuthenticationChecker.php | 1 - .../TwoFactorAuthenticationCheckerFactory.php | 1 - src/Authenticator/SocialAuthenticator.php | 4 -- .../OneTimePasswordAuthenticatorComponent.php | 1 - src/Controller/Traits/LoginTrait.php | 5 --- src/Controller/Traits/SocialTrait.php | 1 - src/Model/Behavior/AuthFinderBehavior.php | 3 +- ...aultTwoFactorAuthenticationCheckerTest.php | 1 - ...FactorAuthenticationCheckerFactoryTest.php | 3 +- .../Authenticator/SocialAuthenticatorTest.php | 35 ----------------- .../SocialPendingEmailAuthenticatorTest.php | 2 - .../Controller/Traits/LoginTraitTest.php | 1 - .../Traits/OneTimePasswordVerifyTraitTest.php | 2 - .../Controller/Traits/SocialTraitTest.php | 1 - .../Traits/UserValidationTraitTest.php | 2 - .../Middleware/SocialAuthMiddlewareTest.php | 39 ------------------- .../Middleware/SocialEmailMiddlewareTest.php | 2 - .../Model/Behavior/RegisterBehaviorTest.php | 1 - 18 files changed, 2 insertions(+), 103 deletions(-) diff --git a/src/Auth/DefaultTwoFactorAuthenticationChecker.php b/src/Auth/DefaultTwoFactorAuthenticationChecker.php index 6b58ee51a..52a8435cc 100644 --- a/src/Auth/DefaultTwoFactorAuthenticationChecker.php +++ b/src/Auth/DefaultTwoFactorAuthenticationChecker.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Auth; use Cake\Core\Configure; -use Cake\Network\Exception\BadRequestException; /** * Default class to check if two factor authentication is enabled and required diff --git a/src/Auth/TwoFactorAuthenticationCheckerFactory.php b/src/Auth/TwoFactorAuthenticationCheckerFactory.php index da62927b3..caf849617 100644 --- a/src/Auth/TwoFactorAuthenticationCheckerFactory.php +++ b/src/Auth/TwoFactorAuthenticationCheckerFactory.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Auth; use Cake\Core\Configure; -use Cake\Network\Exception\BadRequestException; /** * Factory for two authentication checker diff --git a/src/Authenticator/SocialAuthenticator.php b/src/Authenticator/SocialAuthenticator.php index 8a373c411..eb70c6f59 100644 --- a/src/Authenticator/SocialAuthenticator.php +++ b/src/Authenticator/SocialAuthenticator.php @@ -5,13 +5,9 @@ use Authentication\Authenticator\AbstractAuthenticator; use Authentication\Authenticator\Result; use Authentication\UrlChecker\UrlCheckerTrait; -use CakeDC\Users\Exception\AccountNotActiveException; -use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\SocialAuthenticationException; -use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Social\MapUser; use CakeDC\Users\Social\Service\ServiceInterface; -use Cake\Datasource\Exception\RecordNotFoundException; use Cake\Http\Exception\BadRequestException; use Cake\Log\LogTrait; use Psr\Http\Message\ResponseInterface; diff --git a/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php b/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php index 3a4b691c8..75a8bc620 100644 --- a/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php +++ b/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Controller\Component; -use CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface; use Cake\Controller\Component; use Cake\Core\Configure; use RobThree\Auth\TwoFactorAuth; diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index d21251bfb..edf788c1e 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -11,12 +11,7 @@ namespace CakeDC\Users\Controller\Traits; -use Authentication\Authenticator\Result; use CakeDC\Users\Authentication\AuthenticationService; -use CakeDC\Users\Authenticator\AuthenticatorFeedbackInterface; -use CakeDC\Users\Authenticator\FormAuthenticator; -use CakeDC\Users\Authenticator\SocialAuthenticator; -use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Plugin; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; diff --git a/src/Controller/Traits/SocialTrait.php b/src/Controller/Traits/SocialTrait.php index dfc1d540f..4fdbbf015 100644 --- a/src/Controller/Traits/SocialTrait.php +++ b/src/Controller/Traits/SocialTrait.php @@ -11,7 +11,6 @@ namespace CakeDC\Users\Controller\Traits; -use CakeDC\Users\Middleware\SocialAuthMiddleware; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; diff --git a/src/Model/Behavior/AuthFinderBehavior.php b/src/Model/Behavior/AuthFinderBehavior.php index ef51d1fc9..833da5e8f 100644 --- a/src/Model/Behavior/AuthFinderBehavior.php +++ b/src/Model/Behavior/AuthFinderBehavior.php @@ -24,10 +24,9 @@ class AuthFinderBehavior extends Behavior * Custom finder to filter active users * * @param Query $query Query object to modify - * @param array $options Query options * @return Query */ - public function findActive(Query $query, array $options = []) + public function findActive(Query $query) { $query->where([$this->_table->aliasField('active') => 1]); diff --git a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php index a9cb270cf..71ad48bb0 100644 --- a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php +++ b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php @@ -12,7 +12,6 @@ use CakeDC\Users\Auth\DefaultTwoFactorAuthenticationChecker; use Cake\Core\Configure; -use Cake\Network\Exception\BadRequestException; use Cake\TestSuite\TestCase; /** diff --git a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php index 17c612f31..2a5e6957e 100644 --- a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php +++ b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php @@ -12,7 +12,6 @@ use CakeDC\Users\Auth\DefaultTwoFactorAuthenticationChecker; use CakeDC\Users\Auth\TwoFactorAuthenticationCheckerFactory; -use CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface; use Cake\Core\Configure; use Cake\TestSuite\TestCase; @@ -39,6 +38,6 @@ public function testGetCheckerInvalidInterface() Configure::write('OneTimePasswordAuthenticator.checker', 'stdClass'); $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage("Invalid config for 'OneTimePasswordAuthenticator.checker', 'stdClass' does not implement 'CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface'"); - $result = (new TwoFactorAuthenticationCheckerFactory())->build(); + (new TwoFactorAuthenticationCheckerFactory())->build(); } } diff --git a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php index 9af7744f2..0d691aafa 100644 --- a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php @@ -18,9 +18,7 @@ use CakeDC\Users\Exception\SocialAuthenticationException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Model\Entity\User; -use CakeDC\Users\Social\Mapper\Facebook; use CakeDC\Users\Social\MapUser; -use CakeDC\Users\Social\Service\OAuth2Service; use CakeDC\Users\Social\Service\ServiceFactory; use Cake\Core\Configure; use Cake\Http\Response; @@ -259,39 +257,6 @@ public function testAuthenticateGetRawDataNull() 'expires' => 1490988496 ]); - $user = new FacebookUser([ - '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' - ]); - $this->Provider->expects($this->never()) ->method('getAuthorizationUrl'); diff --git a/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php index 7dc4855e9..894e4ef5b 100644 --- a/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php @@ -12,11 +12,9 @@ use Authentication\Authenticator\Result; use Authentication\Identifier\IdentifierCollection; - use CakeDC\Users\Authenticator\SocialPendingEmailAuthenticator; use CakeDC\Users\Model\Entity\User; use CakeDC\Users\Social\Mapper\Facebook; -use CakeDC\Users\Social\MapUser; use Cake\Core\Configure; use Cake\Http\Client\Response; use Cake\Http\ServerRequestFactory; diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index d3204dfc4..3e854d420 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -18,7 +18,6 @@ use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Controller\Component\LoginComponent; -use CakeDC\Users\Middleware\SocialAuthMiddleware; use Cake\Controller\ComponentRegistry; use Cake\Event\Event; use Cake\Http\Response; diff --git a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php index bd81405f0..86deea91c 100644 --- a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php +++ b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php @@ -12,8 +12,6 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; use CakeDC\Users\Controller\Component\OneTimePasswordAuthenticatorComponent; - -use CakeDC\Users\Controller\Traits\OneTimePasswordVerifyTrait; use Cake\Core\Configure; use Cake\Http\ServerRequest; use Cake\ORM\TableRegistry; diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index e671e8601..86b7de025 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -18,7 +18,6 @@ use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Controller\Component\LoginComponent; -use CakeDC\Users\Middleware\SocialAuthMiddleware; use Cake\Controller\ComponentRegistry; use Cake\Event\Event; use Cake\Http\Response; diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index 3747ce850..de597b54f 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -11,9 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use CakeDC\Users\Test\TestCase\Controller\Traits\BaseTraitTest; use Cake\Event\Event; -use Cake\Network\Request; class UserValidationTraitTest extends BaseTraitTest { diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index 21e7112d0..32cbf2a54 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -172,45 +172,6 @@ public function testSuccessfullyAuthenticated() 'provider' => 'facebook' ]); $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); - - $Token = new \League\OAuth2\Client\Token\AccessToken([ - 'access_token' => 'test-token', - 'expires' => 1490988496 - ]); - - $user = new FacebookUser([ - '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' - ]); - $Middleware = new SocialAuthMiddleware(); $ResponseOriginal = new Response(); diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index 6c67c073a..21458ea67 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -2,9 +2,7 @@ namespace CakeDC\Users\Test\TestCase\Middleware; -use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; -use CakeDC\Users\Model\Entity\User; use CakeDC\Users\Social\Mapper\Facebook; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index 0dfa3ffdf..034648d77 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -12,7 +12,6 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; -use CakeDC\Users\Exception\UserAlreadyActiveException; use Cake\Core\Configure; use Cake\Mailer\Email; use Cake\ORM\TableRegistry; From 4efa0b45d2fea323f4384f9f4db70eac53d9fb69 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 16 Nov 2018 17:59:58 -0200 Subject: [PATCH 175/685] Preserving redirect url --- src/Controller/Component/LoginComponent.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index 032c7bf17..311ca4353 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -116,8 +116,12 @@ protected function afterIdentifyUser($user) return $this->getController()->redirect($event->result); } - return $this->getController()->redirect( - $this->getController()->Authentication->getConfig('loginRedirect') - ); + $query = $this->getController()->request->getQueryParams(); + $redirectUrl = $this->getController()->Authentication->getConfig('loginRedirect'); + if (isset($query['redirect'])) { + $redirectUrl = $query['redirect']; + } + + return $this->getController()->redirect($redirectUrl); } } From 0c58085af8e23680cf23133564c069facd8ac412 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 19 Nov 2018 10:20:24 -0200 Subject: [PATCH 176/685] Allowing custom authentication/authorization loader --- src/Plugin.php | 10 +++++++ tests/TestCase/PluginTest.php | 52 +++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/Plugin.php b/src/Plugin.php index deecf90cf..3b60b80e4 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -48,6 +48,11 @@ class Plugin extends BasePlugin implements AuthenticationServiceProviderInterfac */ public function getAuthenticationService(ServerRequestInterface $request, ResponseInterface $response) { + $serviceLoader = Configure::read('Auth.Authentication.service'); + if ($serviceLoader !== null) { + return $serviceLoader($request, $response); + } + return $this->authentication(); } @@ -56,6 +61,11 @@ public function getAuthenticationService(ServerRequestInterface $request, Respon */ public function getAuthorizationService(ServerRequestInterface $request, ResponseInterface $response) { + $serviceLoader = Configure::read('Auth.Authorization.service'); + if ($serviceLoader !== null) { + return $serviceLoader($request, $response); + } + $map = new MapResolver(); $map->map(ServerRequest::class, RbacPolicy::class); diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 417304b28..7e38a4fea 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -11,8 +11,11 @@ use Authorization\AuthorizationService; use Authorization\Middleware\AuthorizationMiddleware; use Authorization\Middleware\RequestAuthorizationMiddleware; +use Authorization\Policy\ResolverCollection; +use Cake\Http\ServerRequestFactory; use CakeDC\Auth\Middleware\RbacMiddleware; use CakeDC\Users\Authentication\AuthenticationService as CakeDCAuthenticationService; +use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\GoogleTwoFactorAuthenticator; use CakeDC\Users\Middleware\OneTimePasswordAuthenticatorMiddleware; @@ -206,6 +209,32 @@ public function testMiddlewareNotGoogleAuthenticationAndNotSocial() $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->get(2)); } + /** + * testGetAuthenticationService + * + * @return void + */ + public function testGetAuthenticationServiceCallableDefined() + { + $request = ServerRequestFactory::fromGlobals(); + $request->withQueryParams(['method' => __METHOD__]); + $response = new Response(['body' => __METHOD__]); + $service = new AuthenticationService([ + 'identifiers' => [ + 'Authentication.Password' + ] + ]); + Configure::write('Auth.Authentication.service', function($aRequest, $aResponse) use ($request, $response, $service) { + $this->assertSame($request, $aRequest); + $this->assertSame($response, $aResponse); + + return $service; + }); + + $plugin = new Plugin(); + $actualService = $plugin->getAuthenticationService($request, $response); + $this->assertSame($service, $actualService); + } /** * testGetAuthenticationService * @@ -395,4 +424,27 @@ public function testGetAuthorizationService() $service = $plugin->getAuthorizationService(new ServerRequest(), new Response()); $this->assertInstanceOf(AuthorizationService::class, $service); } + + /** + * testGetAuthorizationService + * + * @return void + */ + public function testGetAuthorizationServiceCallableDefined() + { + $request = ServerRequestFactory::fromGlobals(); + $request->withQueryParams(['method' => __METHOD__]); + $response = new Response(['body' => __METHOD__]); + $service = new AuthorizationService(new ResolverCollection()); + Configure::write('Auth.Authorization.service', function($aRequest, $aResponse) use ($request, $response, $service) { + $this->assertSame($request, $aRequest); + $this->assertSame($response, $aResponse); + + return $service; + }); + + $plugin = new Plugin(); + $actualService = $plugin->getAuthorizationService($request, $response); + $this->assertSame($service, $actualService); + } } From f58da12b206b978b8c14df553f862365dcd9d2ea Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 19 Nov 2018 18:20:39 -0200 Subject: [PATCH 177/685] Moved social namespace to auth plugin --- config/users.php | 24 +- src/Authenticator/SocialAuthenticator.php | 6 +- src/Controller/Traits/LinkSocialTrait.php | 4 +- src/Exception/InvalidProviderException.php | 31 -- src/Exception/InvalidSettingsException.php | 31 -- src/Middleware/SocialAuthMiddleware.php | 2 +- src/Social/MapUser.php | 43 -- src/Social/Mapper/AbstractMapper.php | 120 ------ src/Social/Mapper/Amazon.php | 48 --- src/Social/Mapper/Facebook.php | 59 --- src/Social/Mapper/Google.php | 47 --- src/Social/Mapper/Instagram.php | 47 --- src/Social/Mapper/LinkedIn.php | 28 -- src/Social/Mapper/Pinterest.php | 24 -- src/Social/Mapper/Tumblr.php | 48 --- src/Social/Mapper/Twitter.php | 67 --- src/Social/ProviderConfig.php | 128 ------ src/Social/Service/OAuth1Service.php | 104 ----- src/Social/Service/OAuth2Service.php | 115 ------ src/Social/Service/OAuthServiceAbstract.php | 38 -- src/Social/Service/ServiceFactory.php | 60 --- src/Social/Service/ServiceInterface.php | 56 --- src/Social/Util/SocialUtils.php | 35 -- .../Authenticator/SocialAuthenticatorTest.php | 8 +- .../SocialPendingEmailAuthenticatorTest.php | 2 +- .../Controller/Traits/LinkSocialTraitTest.php | 4 +- .../InvalidProviderExceptionTest.php | 46 --- .../InvalidSettingsExceptionTest.php | 46 --- .../Identifier/SocialIdentifierTest.php | 2 +- .../Middleware/SocialAuthMiddlewareTest.php | 10 +- .../Middleware/SocialEmailMiddlewareTest.php | 6 +- tests/TestCase/PluginTest.php | 9 +- tests/TestCase/Social/Mapper/FacebookTest.php | 91 ---- tests/TestCase/Social/Mapper/GoogleTest.php | 73 ---- .../TestCase/Social/Mapper/InstagramTest.php | 72 ---- tests/TestCase/Social/Mapper/LinkedInTest.php | 75 ---- tests/TestCase/Social/Mapper/TwitterTest.php | 71 ---- tests/TestCase/Social/ProviderConfigTest.php | 292 ------------- .../Social/Service/OAuth1ServiceTest.php | 357 ---------------- .../Social/Service/OAuth2ServiceTest.php | 388 ------------------ .../Social/Service/ServiceFactoryTest.php | 251 ----------- 41 files changed, 38 insertions(+), 2930 deletions(-) delete mode 100644 src/Exception/InvalidProviderException.php delete mode 100644 src/Exception/InvalidSettingsException.php delete mode 100644 src/Social/MapUser.php delete mode 100644 src/Social/Mapper/AbstractMapper.php delete mode 100644 src/Social/Mapper/Amazon.php delete mode 100644 src/Social/Mapper/Facebook.php delete mode 100644 src/Social/Mapper/Google.php delete mode 100644 src/Social/Mapper/Instagram.php delete mode 100644 src/Social/Mapper/LinkedIn.php delete mode 100644 src/Social/Mapper/Pinterest.php delete mode 100644 src/Social/Mapper/Tumblr.php delete mode 100644 src/Social/Mapper/Twitter.php delete mode 100644 src/Social/ProviderConfig.php delete mode 100644 src/Social/Service/OAuth1Service.php delete mode 100644 src/Social/Service/OAuth2Service.php delete mode 100644 src/Social/Service/OAuthServiceAbstract.php delete mode 100644 src/Social/Service/ServiceFactory.php delete mode 100644 src/Social/Service/ServiceInterface.php delete mode 100644 src/Social/Util/SocialUtils.php delete mode 100644 tests/TestCase/Exception/InvalidProviderExceptionTest.php delete mode 100644 tests/TestCase/Exception/InvalidSettingsExceptionTest.php delete mode 100644 tests/TestCase/Social/Mapper/FacebookTest.php delete mode 100644 tests/TestCase/Social/Mapper/GoogleTest.php delete mode 100644 tests/TestCase/Social/Mapper/InstagramTest.php delete mode 100644 tests/TestCase/Social/Mapper/LinkedInTest.php delete mode 100644 tests/TestCase/Social/Mapper/TwitterTest.php delete mode 100644 tests/TestCase/Social/ProviderConfigTest.php delete mode 100644 tests/TestCase/Social/Service/OAuth1ServiceTest.php delete mode 100644 tests/TestCase/Social/Service/OAuth2ServiceTest.php delete mode 100644 tests/TestCase/Social/Service/ServiceFactoryTest.php diff --git a/config/users.php b/config/users.php index 974446974..2911144cd 100644 --- a/config/users.php +++ b/config/users.php @@ -256,9 +256,9 @@ 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'prefix' => null], 'providers' => [ 'facebook' => [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Auth\Social\Mapper\Facebook', 'options' => [ 'graphApiVersion' => 'v2.8', //bio field was deprecated on >= v2.8 'redirectUri' => Router::fullBaseUrl() . '/auth/facebook', @@ -267,9 +267,9 @@ ] ], 'twitter' => [ - 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', + 'service' => 'CakeDC\Auth\Social\Service\OAuth1Service', 'className' => 'League\OAuth1\Client\Server\Twitter', - 'mapper' => 'CakeDC\Users\Social\Mapper\Twitter', + 'mapper' => 'CakeDC\Auth\Social\Mapper\Twitter', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/twitter', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter', @@ -277,9 +277,9 @@ ] ], 'linkedIn' => [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\LinkedIn', - 'mapper' => 'CakeDC\Users\Social\Mapper\LinkedIn', + 'mapper' => 'CakeDC\Auth\Social\Mapper\LinkedIn', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/linkedIn', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/linkedIn', @@ -287,9 +287,9 @@ ] ], 'instagram' => [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Instagram', - 'mapper' => 'CakeDC\Users\Social\Mapper\Instagram', + 'mapper' => 'CakeDC\Auth\Social\Mapper\Instagram', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/instagram', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/instagram', @@ -297,9 +297,9 @@ ] ], 'google' => [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', 'className' => 'League\OAuth2\Client\Provider\Google', - 'mapper' => 'CakeDC\Users\Social\Mapper\Google', + 'mapper' => 'CakeDC\Auth\Social\Mapper\Google', 'options' => [ 'userFields' => ['url', 'aboutMe'], 'redirectUri' => Router::fullBaseUrl() . '/auth/google', @@ -308,9 +308,9 @@ ] ], 'amazon' => [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', 'className' => 'Luchianenco\OAuth2\Client\Provider\Amazon', - 'mapper' => 'CakeDC\Users\Social\Mapper\Amazon', + 'mapper' => 'CakeDC\Auth\Social\Mapper\Amazon', 'options' => [ 'redirectUri' => Router::fullBaseUrl() . '/auth/amazon', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/amazon', diff --git a/src/Authenticator/SocialAuthenticator.php b/src/Authenticator/SocialAuthenticator.php index eb70c6f59..88426a484 100644 --- a/src/Authenticator/SocialAuthenticator.php +++ b/src/Authenticator/SocialAuthenticator.php @@ -5,9 +5,9 @@ use Authentication\Authenticator\AbstractAuthenticator; use Authentication\Authenticator\Result; use Authentication\UrlChecker\UrlCheckerTrait; +use CakeDC\Auth\Social\MapUser; +use CakeDC\Auth\Social\Service\ServiceInterface; use CakeDC\Users\Exception\SocialAuthenticationException; -use CakeDC\Users\Social\MapUser; -use CakeDC\Users\Social\Service\ServiceInterface; use Cake\Http\Exception\BadRequestException; use Cake\Log\LogTrait; use Psr\Http\Message\ResponseInterface; @@ -16,7 +16,7 @@ /** * Social authenticator * - * Authenticates an identity based on request attribute socialService (CakeDC\Users\Social\Service\ServiceInterface) + * Authenticates an identity based on request attribute socialService (CakeDC\Auth\Social\Service\ServiceInterface) */ class SocialAuthenticator extends AbstractAuthenticator { diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 7f460b3a5..afa6194df 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -11,8 +11,8 @@ namespace CakeDC\Users\Controller\Traits; -use CakeDC\Users\Social\MapUser; -use CakeDC\Users\Social\Service\ServiceFactory; +use CakeDC\Auth\Social\MapUser; +use CakeDC\Auth\Social\Service\ServiceFactory; use Cake\Utility\Hash; /** diff --git a/src/Exception/InvalidProviderException.php b/src/Exception/InvalidProviderException.php deleted file mode 100644 index 84028b813..000000000 --- a/src/Exception/InvalidProviderException.php +++ /dev/null @@ -1,31 +0,0 @@ -getConfig('mapper'); - if (is_string($mapper)) { - $mapper = $this->buildMapper($mapper); - } - - $user = $mapper($data); - $user['provider'] = $service->getProviderName(); - - return $user; - } - - /** - * Build the mapper object - * - * @param string $className of mapper - * - * @return callable - */ - protected function buildMapper($className) - { - if (!class_exists($className)) { - throw new \InvalidArgumentException(__("Provider mapper class {0} does not exist", $className)); - } - - return new $className(); - } -} diff --git a/src/Social/Mapper/AbstractMapper.php b/src/Social/Mapper/AbstractMapper.php deleted file mode 100644 index f7c9ace5b..000000000 --- a/src/Social/Mapper/AbstractMapper.php +++ /dev/null @@ -1,120 +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 $mapFields map fields - */ - public function __construct($mapFields = null) - { - if (!is_null($mapFields)) { - $this->_mapFields = $mapFields; - } - $this->_mapFields = array_merge($this->_defaultMapFields, $this->_mapFields); - } - /** - * Invoke method - * - * @param mixed $rawData raw data - * @return mixed - */ - public function __invoke($rawData) - { - return $this->_map($rawData); - } - - /** - * If email is present the user is validated - * - * @param mixed $rawData raw data - * - * @return bool - */ - protected function _validated($rawData) - { - $email = Hash::get($rawData, $this->_mapFields['email']); - - return !empty($email); - } - - /** - * Maps raw data using mapFields - * - * @param mixed $rawData raw data - * @return mixed - */ - protected function _map($rawData) - { - $result = []; - collection($this->_mapFields)->each(function ($mappedField, $field) use (&$result, $rawData) { - $value = Hash::get($rawData, $mappedField); - $function = '_' . $field; - if (method_exists($this, $function)) { - $value = $this->{$function}($rawData); - } - $result[$field] = $value; - }); - $token = Hash::get($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'] = $rawData; - - return $result; - } -} diff --git a/src/Social/Mapper/Amazon.php b/src/Social/Mapper/Amazon.php deleted file mode 100644 index 34b48ec65..000000000 --- a/src/Social/Mapper/Amazon.php +++ /dev/null @@ -1,48 +0,0 @@ - 'user_id' - ]; - - /** - * Get link property value - * - * @param mixed $rawData raw data - * - * @return string - */ - protected function _link($rawData) - { - return self::AMAZON_BASE_URL . Hash::get($rawData, $this->_mapFields['id']); - } -} diff --git a/src/Social/Mapper/Facebook.php b/src/Social/Mapper/Facebook.php deleted file mode 100644 index caf6caf90..000000000 --- a/src/Social/Mapper/Facebook.php +++ /dev/null @@ -1,59 +0,0 @@ - 'name', - ]; - - /** - * Get avatar url - * - * @param mixed $rawData raw data - * - * @return string - */ - protected function _avatar($rawData) - { - return self::FB_GRAPH_BASE_URL . Hash::get($rawData, 'id') . '/picture?type=large'; - } - - /** - * Get link property value - * - * @param mixed $rawData raw data - * - * @return string - */ - protected function _link($rawData) - { - return Hash::get($rawData, 'link') ?: '#'; - } -} diff --git a/src/Social/Mapper/Google.php b/src/Social/Mapper/Google.php deleted file mode 100644 index e7dcf5923..000000000 --- a/src/Social/Mapper/Google.php +++ /dev/null @@ -1,47 +0,0 @@ - 'image.url', - 'full_name' => 'displayName', - 'email' => 'emails.0.value', - 'first_name' => 'name.givenName', - 'last_name' => 'name.familyName', - 'bio' => 'aboutMe', - 'link' => 'url' - ]; - - /** - * Get link property value - * - * @param mixed $rawData raw data - * - * @return string - */ - protected function _link($rawData) - { - return Hash::get($rawData, $this->_mapFields['link']) ?: '#'; - } -} diff --git a/src/Social/Mapper/Instagram.php b/src/Social/Mapper/Instagram.php deleted file mode 100644 index 4478e2c61..000000000 --- a/src/Social/Mapper/Instagram.php +++ /dev/null @@ -1,47 +0,0 @@ - 'full_name', - 'avatar' => 'profile_picture', - ]; - - /** - * Get link property value - * - * @param mixed $rawData raw data - * - * @return string - */ - protected function _link($rawData) - { - return self::INSTAGRAM_BASE_URL . Hash::get($rawData, $this->_mapFields['username']); - } -} diff --git a/src/Social/Mapper/LinkedIn.php b/src/Social/Mapper/LinkedIn.php deleted file mode 100644 index 24c573b3e..000000000 --- a/src/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/Social/Mapper/Pinterest.php b/src/Social/Mapper/Pinterest.php deleted file mode 100644 index d3206d64e..000000000 --- a/src/Social/Mapper/Pinterest.php +++ /dev/null @@ -1,24 +0,0 @@ - 'image.60x60.url', - 'link' => 'url', - ]; -} diff --git a/src/Social/Mapper/Tumblr.php b/src/Social/Mapper/Tumblr.php deleted file mode 100644 index 0ba1a628e..000000000 --- a/src/Social/Mapper/Tumblr.php +++ /dev/null @@ -1,48 +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' - ]; - - /** - * Get id property value - * - * @param mixed $rawData raw data - * - * @return string - */ - protected function _id($rawData) - { - return crc32($rawData['nickname']); - } -} diff --git a/src/Social/Mapper/Twitter.php b/src/Social/Mapper/Twitter.php deleted file mode 100644 index a4a2085fc..000000000 --- a/src/Social/Mapper/Twitter.php +++ /dev/null @@ -1,67 +0,0 @@ - 'uid', - 'username' => 'nickname', - 'full_name' => 'name', - 'first_name' => 'firstName', - 'last_name' => 'lastName', - 'email' => 'email', - 'avatar' => 'imageUrl', - 'bio' => 'description', - 'validated' => 'validated' - ]; - - /** - * Get link property value - * - * @param mixed $rawData raw data - * - * @return string - */ - protected function _link($rawData) - { - return self::TWITTER_BASE_URL . Hash::get($rawData, $this->_mapFields['username']); - } - - /** - * Get avatar url - * - * @param mixed $rawData raw data - * - * @return string - */ - protected function _avatar($rawData) - { - return str_replace('normal', 'bigger', Hash::get($rawData, $this->_mapFields['avatar'])); - } -} diff --git a/src/Social/ProviderConfig.php b/src/Social/ProviderConfig.php deleted file mode 100644 index f550f8511..000000000 --- a/src/Social/ProviderConfig.php +++ /dev/null @@ -1,128 +0,0 @@ - $options) { - if ($this->_isProviderEnabled($options)) { - $providers[$provider] = $options; - } - } - $oauthConfig['providers'] = $providers; - - $this->providers = $this->normalizeConfig(Hash::merge($config, $oauthConfig))['providers']; - } - - /** - * Normalizes providers' configuration. - * - * @param array $config Array of config to normalize. - * @return array - * @throws \Exception - */ - public function normalizeConfig(array $config) - { - 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, - 'service' => null, - 'mapper' => null, - 'options' => [], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - ] + $parent; - - $config = array_intersect_key($config, $defaults); - $config += $defaults; - - array_walk($config, [$this, '_validateConfig']); - - foreach (['options', 'collaborators', 'signature'] 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\Exception\InvalidProviderException - * @throws \CakeDC\Users\Exception\InvalidSettingsException - */ - protected function _validateConfig(&$value, $key) - { - if (in_array($key, ['className', 'service', 'mapper'], true) && !is_object($value) && !class_exists($value)) { - throw new InvalidProviderException([$value]); - } elseif (!is_array($value) && in_array($key, ['options', 'collaborators'])) { - throw new InvalidSettingsException([$key]); - } - } - - /** - * 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 provider config - * - * @param string $alias for provider - * @return array - */ - public function getConfig($alias): array - { - return Hash::get($this->providers, $alias, []); - } -} diff --git a/src/Social/Service/OAuth1Service.php b/src/Social/Service/OAuth1Service.php deleted file mode 100644 index b49cf5345..000000000 --- a/src/Social/Service/OAuth1Service.php +++ /dev/null @@ -1,104 +0,0 @@ - 'clientId', - 'secret' => 'clientSecret', - 'callback_uri' => 'redirectUri' - ]; - - foreach ($map as $to => $from) { - if (array_key_exists($from, $providerConfig['options'])) { - $providerConfig['options'][$to] = $providerConfig['options'][$from]; - unset($providerConfig['options'][$from]); - } - } - $providerConfig += ['signature' => null]; - $this->setProvider($providerConfig); - $this->setConfig($providerConfig); - } - - /** - * Check if we are at getUserStep, meaning, we received a callback from provider. - * - * @param \Cake\Http\ServerRequest $request Request object. - * @return bool - */ - public function isGetUserStep(ServerRequest $request): bool - { - $oauthToken = $request->getQuery('oauth_token'); - $oauthVerifier = $request->getQuery('oauth_verifier'); - - return !empty($oauthToken) && !empty($oauthVerifier); - } - - /** - * Get a authentication url for user - * - * @param \Cake\Http\ServerRequest $request Request object. - * @return string - */ - public function getAuthorizationUrl(ServerRequest $request) - { - $temporaryCredentials = $this->provider->getTemporaryCredentials(); - $request->getSession()->write('temporary_credentials', $temporaryCredentials); - - return $this->provider->getAuthorizationUrl($temporaryCredentials); - } - - /** - * Get a user in social provider - * - * @param \Cake\Http\ServerRequest $request Request object. - * @return array - */ - public function getUser(ServerRequest $request): array - { - $oauthToken = $request->getQuery('oauth_token'); - $oauthVerifier = $request->getQuery('oauth_verifier'); - - $temporaryCredentials = $request->getSession()->read('temporary_credentials'); - $tokenCredentials = $this->provider->getTokenCredentials($temporaryCredentials, $oauthToken, $oauthVerifier); - $user = (array)$this->provider->getUserDetails($tokenCredentials); - $user['token'] = [ - 'accessToken' => $tokenCredentials->getIdentifier(), - 'tokenSecret' => $tokenCredentials->getSecret(), - ]; - - return $user; - } - - /** - * Instantiates provider object. - * - * @param array $config for provider. - * @return void - */ - protected function setProvider($config) - { - if (is_object($config['className']) && $config['className'] instanceof Server) { - $this->provider = $config['className']; - } else { - $class = $config['className']; - - $this->provider = new $class($config['options'], $config['signature']); - } - } -} diff --git a/src/Social/Service/OAuth2Service.php b/src/Social/Service/OAuth2Service.php deleted file mode 100644 index c7bd0d244..000000000 --- a/src/Social/Service/OAuth2Service.php +++ /dev/null @@ -1,115 +0,0 @@ -setProvider($providerConfig); - $this->setConfig($providerConfig); - } - - /** - * Check if we are at getUserStep, meaning, we received a callback from provider. - * Return true when querystring code is not empty - * - * @param \Cake\Http\ServerRequest $request Request object. - * @return bool - */ - public function isGetUserStep(ServerRequest $request): bool - { - return !empty($request->getQuery('code')); - } - - /** - * Get a authentication url for user - * - * @param \Cake\Http\ServerRequest $request Request object. - * @return string - */ - public function getAuthorizationUrl(ServerRequest $request) - { - if ($this->getConfig('options.state')) { - $request->getSession()->write('oauth2state', $this->provider->getState()); - } - - return $this->provider->getAuthorizationUrl(); - } - - /** - * Get a user in social provider - * - * @param \Cake\Http\ServerRequest $request Request object. - * - * @throws BadRequestException when oauth2 state is invalid - * @return array - */ - public function getUser(ServerRequest $request): array - { - if (!$this->validate($request)) { - throw new BadRequestException('Invalid OAuth2 state'); - } - - $code = $request->getQuery('code'); - $token = $this->provider->getAccessToken('authorization_code', compact('code')); - - return compact('token') + $this->provider->getResourceOwner($token)->toArray(); - } - - /** - * Validates OAuth2 request. - * - * @param \Cake\Http\ServerRequest $request Request object. - * @return bool - */ - protected function validate(ServerRequest $request) - { - if (!array_key_exists('code', $request->getQueryParams())) { - 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; - } - - /** - * Instantiates provider object. - * - * @param array $config for provider. - * @return void - */ - protected function setProvider($config) - { - if (is_object($config['className']) && $config['className'] instanceof AbstractProvider) { - $this->provider = $config['className']; - } else { - $class = $config['className']; - - $this->provider = new $class($config['options'], $config['collaborators']); - } - } -} diff --git a/src/Social/Service/OAuthServiceAbstract.php b/src/Social/Service/OAuthServiceAbstract.php deleted file mode 100644 index 66ef99b1c..000000000 --- a/src/Social/Service/OAuthServiceAbstract.php +++ /dev/null @@ -1,38 +0,0 @@ -providerName; - } - - /** - * Set the social provider name - * - * @param string $providerName social provider - * @return void - */ - public function setProviderName(string $providerName) - { - $this->providerName = $providerName; - } -} diff --git a/src/Social/Service/ServiceFactory.php b/src/Social/Service/ServiceFactory.php deleted file mode 100644 index fd08e9a98..000000000 --- a/src/Social/Service/ServiceFactory.php +++ /dev/null @@ -1,60 +0,0 @@ -redirectUriField = $redirectUriField; - - return $this; - } - - /** - * Create a new service based on provider alias - * - * @param string $provider provider alias - * - * @return ServiceInterface - */ - public function createFromProvider($provider): ServiceInterface - { - $config = (new ProviderConfig())->getConfig($provider); - - if (!$provider || !$config) { - throw new NotFoundException('Provider not found'); - } - - $config['options']['redirectUri'] = $config['options'][$this->redirectUriField]; - unset($config['options']['linkSocialUri'], $config['options']['callbackLinkSocialUri']); - $service = new $config['service']($config); - $service->setProviderName($provider); - - return $service; - } - - /** - * Create a new service based on request - * - * @param ServerRequest $request in use - * - * @return ServiceInterface - */ - public function createFromRequest(ServerRequest $request): ServiceInterface - { - return $this->createFromProvider($request->getAttribute('params')['provider'] ?? null); - } -} diff --git a/src/Social/Service/ServiceInterface.php b/src/Social/Service/ServiceInterface.php deleted file mode 100644 index c3861a904..000000000 --- a/src/Social/Service/ServiceInterface.php +++ /dev/null @@ -1,56 +0,0 @@ -getShortName(); - } -} diff --git a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php index 0d691aafa..047cc8fd5 100644 --- a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php @@ -12,14 +12,14 @@ use Authentication\Authenticator\Result; use Authentication\Identifier\IdentifierCollection; +use CakeDC\Auth\Social\MapUser; +use CakeDC\Auth\Social\Service\ServiceFactory; use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Exception\AccountNotActiveException; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\SocialAuthenticationException; use CakeDC\Users\Exception\UserNotActiveException; use CakeDC\Users\Model\Entity\User; -use CakeDC\Users\Social\MapUser; -use CakeDC\Users\Social\Service\ServiceFactory; use Cake\Core\Configure; use Cake\Http\Response; use Cake\Http\ServerRequestFactory; @@ -76,9 +76,9 @@ public function setUp() ])->getMock(); $config = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', 'className' => $this->Provider, - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Auth\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__', 'graphApiVersion' => 'v2.8', diff --git a/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php index 894e4ef5b..4ecb1895f 100644 --- a/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php @@ -12,9 +12,9 @@ use Authentication\Authenticator\Result; use Authentication\Identifier\IdentifierCollection; +use CakeDC\Auth\Social\Mapper\Facebook; use CakeDC\Users\Authenticator\SocialPendingEmailAuthenticator; use CakeDC\Users\Model\Entity\User; -use CakeDC\Users\Social\Mapper\Facebook; use Cake\Core\Configure; use Cake\Http\Client\Response; use Cake\Http\ServerRequestFactory; diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 903fe4981..b7e5bd8d8 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -76,9 +76,9 @@ public function setUp() ])->getMock(); $config = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', 'className' => $this->Provider, - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Auth\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__', 'graphApiVersion' => 'v2.8', diff --git a/tests/TestCase/Exception/InvalidProviderExceptionTest.php b/tests/TestCase/Exception/InvalidProviderExceptionTest.php deleted file mode 100644 index ea4fa57c5..000000000 --- a/tests/TestCase/Exception/InvalidProviderExceptionTest.php +++ /dev/null @@ -1,46 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Exception/InvalidSettingsExceptionTest.php b/tests/TestCase/Exception/InvalidSettingsExceptionTest.php deleted file mode 100644 index e28c7b2b0..000000000 --- a/tests/TestCase/Exception/InvalidSettingsExceptionTest.php +++ /dev/null @@ -1,46 +0,0 @@ -assertEquals('message', $exception->getMessage()); - } -} diff --git a/tests/TestCase/Identifier/SocialIdentifierTest.php b/tests/TestCase/Identifier/SocialIdentifierTest.php index d40afc8db..3054fd1f3 100644 --- a/tests/TestCase/Identifier/SocialIdentifierTest.php +++ b/tests/TestCase/Identifier/SocialIdentifierTest.php @@ -10,9 +10,9 @@ */ namespace CakeDC\Users\Test\TestCase\Identifier; +use CakeDC\Auth\Social\Mapper\Facebook; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Identifier\SocialIdentifier; -use CakeDC\Users\Social\Mapper\Facebook; use Cake\TestSuite\TestCase; class SocialIdentifierTest extends TestCase diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index 32cbf2a54..8bbf9b827 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -8,12 +8,12 @@ namespace CakeDC\Users\Test\TestCase\Middleware; +use CakeDC\Auth\Social\MapUser; +use CakeDC\Auth\Social\Service\OAuth2Service; +use CakeDC\Auth\Social\Service\ServiceFactory; use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\SocialAuthenticationException; use CakeDC\Users\Middleware\SocialAuthMiddleware; -use CakeDC\Users\Social\MapUser; -use CakeDC\Users\Social\Service\OAuth2Service; -use CakeDC\Users\Social\Service\ServiceFactory; use Cake\Core\Configure; use Cake\Http\Response; use Cake\Http\ServerRequest; @@ -67,9 +67,9 @@ public function setUp() ])->getMock(); $config = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', + 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', 'className' => $this->Provider, - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', + 'mapper' => 'CakeDC\Auth\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__', 'graphApiVersion' => 'v2.8', diff --git a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php index 21458ea67..29a1e7351 100644 --- a/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialEmailMiddlewareTest.php @@ -2,8 +2,8 @@ namespace CakeDC\Users\Test\TestCase\Middleware; +use CakeDC\Auth\Social\Mapper\Facebook; use CakeDC\Users\Middleware\SocialEmailMiddleware; -use CakeDC\Users\Social\Mapper\Facebook; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; use Cake\Http\Response; @@ -36,8 +36,8 @@ public function setUp() parent::setUp(); $config = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', + 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', + 'mapper' => 'CakeDC\Auth\Social\Mapper\Facebook', 'options' => [ 'state' => '__TEST_STATE__', 'graphApiVersion' => 'v2.8', diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 7e38a4fea..af8b3a45b 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -12,10 +12,8 @@ use Authorization\Middleware\AuthorizationMiddleware; use Authorization\Middleware\RequestAuthorizationMiddleware; use Authorization\Policy\ResolverCollection; -use Cake\Http\ServerRequestFactory; use CakeDC\Auth\Middleware\RbacMiddleware; use CakeDC\Users\Authentication\AuthenticationService as CakeDCAuthenticationService; -use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\GoogleTwoFactorAuthenticator; use CakeDC\Users\Middleware\OneTimePasswordAuthenticatorMiddleware; @@ -26,6 +24,7 @@ use Cake\Http\MiddlewareQueue; use Cake\Http\Response; use Cake\Http\ServerRequest; +use Cake\Http\ServerRequestFactory; use Cake\TestSuite\IntegrationTestCase; /** @@ -219,12 +218,12 @@ public function testGetAuthenticationServiceCallableDefined() $request = ServerRequestFactory::fromGlobals(); $request->withQueryParams(['method' => __METHOD__]); $response = new Response(['body' => __METHOD__]); - $service = new AuthenticationService([ + $service = new CakeDCAuthenticationService([ 'identifiers' => [ 'Authentication.Password' ] ]); - Configure::write('Auth.Authentication.service', function($aRequest, $aResponse) use ($request, $response, $service) { + Configure::write('Auth.Authentication.service', function ($aRequest, $aResponse) use ($request, $response, $service) { $this->assertSame($request, $aRequest); $this->assertSame($response, $aResponse); @@ -436,7 +435,7 @@ public function testGetAuthorizationServiceCallableDefined() $request->withQueryParams(['method' => __METHOD__]); $response = new Response(['body' => __METHOD__]); $service = new AuthorizationService(new ResolverCollection()); - Configure::write('Auth.Authorization.service', function($aRequest, $aResponse) use ($request, $response, $service) { + Configure::write('Auth.Authorization.service', function ($aRequest, $aResponse) use ($request, $response, $service) { $this->assertSame($request, $aRequest); $this->assertSame($response, $aResponse); diff --git a/tests/TestCase/Social/Mapper/FacebookTest.php b/tests/TestCase/Social/Mapper/FacebookTest.php deleted file mode 100644 index 78c595173..000000000 --- a/tests/TestCase/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(); - $user = $providerMapper($rawData); - $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/Social/Mapper/GoogleTest.php b/tests/TestCase/Social/Mapper/GoogleTest.php deleted file mode 100644 index 67a1c761c..000000000 --- a/tests/TestCase/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(); - $user = $providerMapper($rawData); - $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/Social/Mapper/InstagramTest.php b/tests/TestCase/Social/Mapper/InstagramTest.php deleted file mode 100644 index 9ae7b7d53..000000000 --- a/tests/TestCase/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(); - $user = $providerMapper($rawData); - $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/Social/Mapper/LinkedInTest.php b/tests/TestCase/Social/Mapper/LinkedInTest.php deleted file mode 100644 index 29a14c3fa..000000000 --- a/tests/TestCase/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(); - $user = $providerMapper($rawData); - $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/Social/Mapper/TwitterTest.php b/tests/TestCase/Social/Mapper/TwitterTest.php deleted file mode 100644 index 02ab53b1c..000000000 --- a/tests/TestCase/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(); - $user = $providerMapper($rawData); - $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/Social/ProviderConfigTest.php b/tests/TestCase/Social/ProviderConfigTest.php deleted file mode 100644 index 13987cce7..000000000 --- a/tests/TestCase/Social/ProviderConfigTest.php +++ /dev/null @@ -1,292 +0,0 @@ -expectException(InvalidProviderException::class); - new ProviderConfig(); - } - - /** - * Test with invalid service class - * - * @return void - */ - public function testWithInvalidServiceClass() - { - Configure::write('OAuth.providers.facebook.options.clientId', '10003030300303'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'secretpassword'); - Configure::write('OAuth.providers.facebook.service', 'CakeDC\Users\Social\Service\InvalidOAuth2Service'); - - $this->expectException(InvalidProviderException::class); - new ProviderConfig(); - } - - /** - * Test with invalid mapper class - * - * @return void - */ - public function testWithInvalidMapperClass() - { - Configure::write('OAuth.providers.facebook.options.clientId', '10003030300303'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'secretpassword'); - Configure::write('OAuth.providers.facebook.mapper', 'CakeDC\Users\Social\Mapper\InvalidFacebook'); - - $this->expectException(InvalidProviderException::class); - new ProviderConfig(); - } - - /** - * Test with invalid settings options value type - * - * @return void - */ - public function testWithInvalidOptionsValueType() - { - $this->expectException(InvalidSettingsException::class); - $config = [ - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ], - 'providers' => [ - 'facebook' => [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', - 'options' => 'invalid options' - ], - ] - ]; - (new ProviderConfig())->normalizeConfig($config); - } - - /** - * Test with invalid settings collaborators value type - * - * @return void - */ - public function testWithInvalidCollaboratorsValueType() - { - Configure::write('OAuth.providers.facebook.options.clientId', '10003030300303'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'secretpassword'); - Configure::write('OAuth.providers.facebook.collaborators', 'johndoe'); - - $this->expectException(InvalidSettingsException::class); - new ProviderConfig(); - } - - /** - * Test with custom config - * - * @return void - */ - public function testWithCustomConfig() - { - Configure::write('OAuth.providers.facebook.options.clientId', '10003030300303'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'secretpassword'); - Configure::write('OAuth.providers.twitter.options.clientId', '20003030300303'); - Configure::write('OAuth.providers.twitter.options.clientSecret', 'weakpassword'); - Configure::write('OAuth.providers.amazon.options.clientId', '3003030300303'); - Configure::write('OAuth.providers.amazon.options.clientSecret', 'weaksecretpassword'); - - $Config = new ProviderConfig([ - 'options' => [ - 'customOption' => 'hello' - ], - ]); - $expected = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', - 'options' => [ - 'customOption' => 'hello', - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => '10003030300303', - 'clientSecret' => 'secretpassword' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]; - $actual = $Config->getConfig('facebook'); - $this->assertEquals($expected, $actual); - } - - /** - * Test with providers enabled - * - * @return void - */ - public function testWithProvidersEnabled() - { - Configure::write('OAuth.providers.facebook.options.clientId', '10003030300303'); - Configure::write('OAuth.providers.facebook.options.clientSecret', 'secretpassword'); - Configure::write('OAuth.providers.twitter.options.clientId', '20003030300303'); - Configure::write('OAuth.providers.twitter.options.clientSecret', 'weakpassword'); - Configure::write('OAuth.providers.amazon.options.clientId', '3003030300303'); - Configure::write('OAuth.providers.amazon.options.clientSecret', 'weaksecretpassword'); - - $Config = new ProviderConfig(); - $expected = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', - 'options' => [ - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => '10003030300303', - 'clientSecret' => 'secretpassword' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]; - $actual = $Config->getConfig('facebook'); - - $this->assertEquals($expected, $actual); - - $expected = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', - 'className' => 'League\OAuth1\Client\Server\Twitter', - 'mapper' => 'CakeDC\Users\Social\Mapper\Twitter', - 'options' => [ - 'redirectUri' => '/auth/twitter', - 'linkSocialUri' => '/link-social/twitter', - 'callbackLinkSocialUri' => '/callback-link-social/twitter', - 'clientId' => '20003030300303', - 'clientSecret' => 'weakpassword' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]; - $actual = $Config->getConfig('twitter'); - $this->assertEquals($expected, $actual); - - $expected = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', - 'className' => 'Luchianenco\OAuth2\Client\Provider\Amazon', - 'mapper' => 'CakeDC\Users\Social\Mapper\Amazon', - 'options' => [ - 'redirectUri' => '/auth/amazon', - 'linkSocialUri' => '/link-social/amazon', - 'callbackLinkSocialUri' => '/callback-link-social/amazon', - 'clientId' => '3003030300303', - 'clientSecret' => 'weaksecretpassword' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]; - $actual = $Config->getConfig('amazon'); - $this->assertEquals($expected, $actual); - - $expected = []; - $actual = $Config->getConfig('linkedIn'); - $this->assertEquals($expected, $actual); - - $expected = []; - $actual = $Config->getConfig('instagram'); - $this->assertEquals($expected, $actual); - - $expected = []; - $actual = $Config->getConfig('google'); - $this->assertEquals($expected, $actual); - } - - /** - * Test without providers enabled - * - * @return void - */ - public function testWithoutProvidersEnabled() - { - $Config = new ProviderConfig(); - $expected = []; - $actual = $Config->getConfig('facebook'); - $this->assertEquals($expected, $actual); - - $expected = []; - $actual = $Config->getConfig('twitter'); - $this->assertEquals($expected, $actual); - - $expected = []; - $actual = $Config->getConfig('amazon'); - $this->assertEquals($expected, $actual); - - $expected = []; - $actual = $Config->getConfig('linkedIn'); - $this->assertEquals($expected, $actual); - - $expected = []; - $actual = $Config->getConfig('instagram'); - $this->assertEquals($expected, $actual); - - $expected = []; - $actual = $Config->getConfig('google'); - $this->assertEquals($expected, $actual); - } -} diff --git a/tests/TestCase/Social/Service/OAuth1ServiceTest.php b/tests/TestCase/Social/Service/OAuth1ServiceTest.php deleted file mode 100644 index 56ba6130e..000000000 --- a/tests/TestCase/Social/Service/OAuth1ServiceTest.php +++ /dev/null @@ -1,357 +0,0 @@ -Provider = $this->getMockBuilder('\League\OAuth1\Client\Server\Twitter')->setConstructorArgs([ - [ - 'redirectUri' => '/auth/twitter', - 'linkSocialUri' => '/link-social/twitter', - 'callback_uri' => '/callback-link-social/twitter', - 'identifier' => '20003030300303', - 'secret' => 'weakpassword', 'identifier' => 'clientId', - ], - ])->setMethods([ - 'getTemporaryCredentials', 'getAuthorizationUrl', 'getTokenCredentials', 'getUserDetails' - ])->getMock(); - - $config = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', - 'className' => $this->Provider, - 'mapper' => 'CakeDC\Users\Social\Mapper\Twitter', - 'options' => [], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]; - - $this->Service = new OAuth1Service($config); - - $this->Request = ServerRequestFactory::fromGlobals(); - } - - /** - * teardown any static object changes and restore them. - * - * @return void - */ - public function tearDown() - { - parent::tearDown(); - - unset($this->Provider, $this->Service, $this->Request); - } - - /** - * Test construct - * - * @return void - */ - public function testConstruct() - { - $service = new OAuth1Service([ - 'className' => 'League\OAuth1\Client\Server\Twitter', - 'mapper' => 'CakeDC\Users\Social\Mapper\Twitter', - 'options' => [ - 'redirectUri' => '/auth/twitter', - 'linkSocialUri' => '/link-social/twitter', - 'callbackLinkSocialUri' => '/callback-link-social/twitter', - 'clientId' => '20003030300303', - 'clientSecret' => 'weakpassword' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]); - $this->assertInstanceOf(ServiceInterface::class, $service); - } - - /** - * Test getAuthorizationUrl - * - * @return void - */ - public function testGetAuthorizationUrl() - { - $Credentials = new TemporaryCredentials(); - $Credentials->setIdentifier('404405646989097789546879'); - $Credentials->setSecret('secretpasword'); - - $this->Provider->expects($this->at(0)) - ->method('getTemporaryCredentials') - ->will($this->returnValue($Credentials)); - - $this->Provider->expects($this->at(1)) - ->method('getAuthorizationUrl') - ->with( - $this->equalTo($Credentials) - ) - ->will($this->returnValue('http://twitter.com/redirect/url')); - - $actual = $this->Service->getAuthorizationUrl($this->Request); - $expected = 'http://twitter.com/redirect/url'; - $this->assertEquals($expected, $actual); - - $expected = $Credentials; - $actual = $this->Request->getSession()->read('temporary_credentials'); - $this->assertEquals($expected, $actual); - } - - /** - * Test isGetUserStep, should return true - * - * @return void - */ - public function testIsGetUserStep() - { - $uri = new Uri('/login'); - - $sessionConfig = (array)Configure::read('Session') + [ - 'defaults' => 'php', - ]; - $session = Session::create($sessionConfig); - $this->Request = new ServerRequest([ - 'uri' => $uri, - 'session' => $session, - ]); - $this->Request = $this->Request->withQueryParams([ - 'oauth_token' => 'dfio39972j3092304230', - 'oauth_verifier' => '21312h2312390839012', - ]); - - $result = $this->Service->isGetUserStep($this->Request); - $this->assertTrue($result); - } - - /** - * Test isGetUserStep, when values are empty - * - * @return void - */ - public function testIsGetUserStepWhenAllEmpty() - { - $uri = new Uri('/login'); - - $sessionConfig = (array)Configure::read('Session') + [ - 'defaults' => 'php', - ]; - $session = Session::create($sessionConfig); - $this->Request = new ServerRequest([ - 'uri' => $uri, - 'session' => $session, - ]); - $this->Request = $this->Request->withQueryParams([ - 'oauth_token' => '', - 'oauth_verifier' => '', - ]); - - $result = $this->Service->isGetUserStep($this->Request); - $this->assertFalse($result); - } - - /** - * Test isGetUserStep, when oauth_token value is empty - * - * @return void - */ - public function testIsGetUserStepWhenOauthTokenEmpty() - { - $uri = new Uri('/login'); - - $sessionConfig = (array)Configure::read('Session') + [ - 'defaults' => 'php', - ]; - $session = Session::create($sessionConfig); - $this->Request = new ServerRequest([ - 'uri' => $uri, - 'session' => $session, - ]); - $this->Request = $this->Request->withQueryParams([ - 'oauth_token' => '', - 'oauth_verifier' => '21312h2312390839012', - ]); - - $result = $this->Service->isGetUserStep($this->Request); - $this->assertFalse($result); - } - - /** - * Test isGetUserStep, when oauth_verifier value is empty - * - * @return void - */ - public function testIsGetUserStepWhenOauthVerifierEmpty() - { - $uri = new Uri('/login'); - - $sessionConfig = (array)Configure::read('Session') + [ - 'defaults' => 'php', - ]; - $session = Session::create($sessionConfig); - $this->Request = new ServerRequest([ - 'uri' => $uri, - 'session' => $session, - ]); - $this->Request = $this->Request->withQueryParams([ - 'oauth_token' => 'dfio39972j3092304230', - 'oauth_verifier' => '', - ]); - - $result = $this->Service->isGetUserStep($this->Request); - $this->assertFalse($result); - } - - /** - * Test isGetUserStep, when keys not present - * - * @return void - */ - public function testIsGetUserStepWhenOauthKeysNotPresent() - { - $uri = new Uri('/login'); - - $sessionConfig = (array)Configure::read('Session') + [ - 'defaults' => 'php', - ]; - $session = Session::create($sessionConfig); - $this->Request = new ServerRequest([ - 'uri' => $uri, - 'session' => $session, - ]); - - $result = $this->Service->isGetUserStep($this->Request); - $this->assertFalse($result); - } - - /** - * Test getUser method - * - * @return void - */ - public function testGetUser() - { - $this->Request = $this->Request->withQueryParams([ - 'oauth_token' => 'good39972j3092304230', - 'oauth_verifier' => '77312h2312390839012', - ]); - - $Credentials = new TemporaryCredentials(); - $Credentials->setIdentifier('404405646989097789546879'); - $Credentials->setSecret('secretpasword'); - $this->Request->getSession()->write('temporary_credentials', $Credentials); - - $TokenCredentials = new TokenCredentials(); - $TokenCredentials->setSecret('tokensecretpasswordnew'); - $TokenCredentials->setIdentifier('50589595670964649809890'); - - $user = new User(); - - $user->uid = '5698297389-2332-89879'; - $user->nickname = 'rmarcelo'; - $user->name = 'Marcelo'; - $user->location = 'Brazil'; - $user->description = 'Developer'; - $user->imageUrl = null; - $user->email = 'example@example.com'; - - $this->Provider->expects($this->never()) - ->method('getTemporaryCredentials'); - - $this->Provider->expects($this->at(0)) - ->method('getTokenCredentials') - ->with( - $this->equalTo($Credentials), - $this->equalTo('good39972j3092304230'), - $this->equalTo('77312h2312390839012') - ) - ->will($this->returnValue($TokenCredentials)); - - $this->Provider->expects($this->at(1)) - ->method('getUserDetails') - ->with( - $this->equalTo($TokenCredentials) - ) - ->will($this->returnValue($user)); - - $actual = $this->Service->getUser($this->Request); - - $expected = [ - 'uid' => '5698297389-2332-89879', - 'nickname' => 'rmarcelo', - 'name' => 'Marcelo', - 'firstName' => null, - 'lastName' => null, - 'email' => 'example@example.com', - 'location' => 'Brazil', - 'description' => 'Developer', - 'imageUrl' => null, - 'urls' => [], - 'extra' => [], - 'token' => [ - 'accessToken' => '50589595670964649809890', - 'tokenSecret' => 'tokensecretpasswordnew' - ] - ]; - $this->assertEquals($expected, $actual); - } -} diff --git a/tests/TestCase/Social/Service/OAuth2ServiceTest.php b/tests/TestCase/Social/Service/OAuth2ServiceTest.php deleted file mode 100644 index 99a70fdd9..000000000 --- a/tests/TestCase/Social/Service/OAuth2ServiceTest.php +++ /dev/null @@ -1,388 +0,0 @@ -Provider = $this->getMockBuilder('\League\OAuth2\Client\Provider\Facebook')->setConstructorArgs([ - [ - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => '10003030300303', - 'clientSecret' => 'secretpassword' - ], - [] - ])->setMethods([ - 'getAccessToken', 'getState', 'getAuthorizationUrl', 'getResourceOwner' - ])->getMock(); - - $config = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', - 'className' => $this->Provider, - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', - 'options' => [ - 'state' => '__TEST_STATE__' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]; - - $this->Service = new OAuth2Service($config); - - $this->Request = ServerRequestFactory::fromGlobals(); - } - - /** - * teardown any static object changes and restore them. - * - * @return void - */ - public function tearDown() - { - parent::tearDown(); - - unset($this->Provider, $this->Service, $this->Request); - } - - /** - * Test construct - * - * @return void - */ - public function testConstruct() - { - $service = new OAuth2Service([ - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', - 'options' => [ - 'customOption' => 'hello', - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => '10003030300303', - 'clientSecret' => 'secretpassword' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]); - $this->assertInstanceOf(ServiceInterface::class, $service); - } - - /** - * Test isGetUserStep, should return true - * - * @return void - */ - public function testIsGetUserStep() - { - $uri = new Uri('/login'); - - $sessionConfig = (array)Configure::read('Session') + [ - 'defaults' => 'php', - ]; - $session = Session::create($sessionConfig); - $this->Request = new ServerRequest([ - 'uri' => $uri, - 'session' => $session, - ]); - $this->Request = $this->Request->withQueryParams([ - 'code' => 'ZPO9972j3092304230', - ]); - - $result = $this->Service->isGetUserStep($this->Request); - $this->assertTrue($result); - } - - /** - * Test isGetUserStep, when values is empty - * - * @return void - */ - public function testIsGetUserStepWhenEmpty() - { - $uri = new Uri('/login'); - - $sessionConfig = (array)Configure::read('Session') + [ - 'defaults' => 'php', - ]; - $session = Session::create($sessionConfig); - $this->Request = new ServerRequest([ - 'uri' => $uri, - 'session' => $session, - ]); - $this->Request = $this->Request->withQueryParams([ - 'code' => '', - ]); - - $result = $this->Service->isGetUserStep($this->Request); - $this->assertFalse($result); - } - - /** - * Test isGetUserStep, when values is not provided - * - * @return void - */ - public function testIsGetUserStepWhenNotProvided() - { - $uri = new Uri('/login'); - - $sessionConfig = (array)Configure::read('Session') + [ - 'defaults' => 'php', - ]; - $session = Session::create($sessionConfig); - $this->Request = new ServerRequest([ - 'uri' => $uri, - 'session' => $session, - ]); - - $result = $this->Service->isGetUserStep($this->Request); - $this->assertFalse($result); - } - - /** - * Test getAuthorizationUrl method - * - * @return void - */ - public function testGetAuthorizationUrl() - { - $this->Provider->expects($this->at(0)) - ->method('getState') - ->will($this->returnValue('_NEW_STATE_')); - - $this->Provider->expects($this->at(1)) - ->method('getAuthorizationUrl') - ->will($this->returnValue('http://facebook.com/redirect/url')); - - $actual = $this->Service->getAuthorizationUrl($this->Request); - $expected = 'http://facebook.com/redirect/url'; - $this->assertEquals($expected, $actual); - - $actual = $this->Request->getSession()->read('oauth2state'); - $expected = '_NEW_STATE_'; - $this->assertEquals($expected, $actual); - } - - /** - * Test getUser method - * - * @return void - */ - public function testGetUser() - { - $this->Request = $this->Request->withQueryParams([ - 'code' => 'ZPO9972j3092304230', - 'state' => '__TEST_STATE__' - ]); - $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); - - $Token = new \League\OAuth2\Client\Token\AccessToken([ - 'access_token' => 'test-token', - 'expires' => 1490988496 - ]); - - $user = new FacebookUser([ - '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' - ]); - - $this->Provider->expects($this->never()) - ->method('getAuthorizationUrl'); - - $this->Provider->expects($this->never()) - ->method('getState'); - - $this->Provider->expects($this->at(0)) - ->method('getAccessToken') - ->with( - $this->equalTo('authorization_code'), - $this->equalTo(['code' => 'ZPO9972j3092304230']) - ) - ->will($this->returnValue($Token)); - - $this->Provider->expects($this->at(1)) - ->method('getResourceOwner') - ->with( - $this->equalTo($Token) - ) - ->will($this->returnValue($user)); - - $actual = $this->Service->getUser($this->Request); - - $expected = [ - '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' - ]; - - $this->assertEquals($expected, $actual); - } - - /** - * Test getUser method, state not equal - * - * @return void - */ - public function testGetUserStateNotEqual() - { - $this->Request = $this->Request->withQueryParams([ - 'code' => 'ZPO9972j3092304230', - 'state' => '__Unknown_State__' - ]); - $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); - - $this->Provider->expects($this->never()) - ->method('getAuthorizationUrl'); - - $this->Provider->expects($this->never()) - ->method('getState'); - - $this->Provider->expects($this->never()) - ->method('getAccessToken'); - - $this->Provider->expects($this->never()) - ->method('getResourceOwner'); - - $this->expectException(BadRequestException::class); - $this->Service->getUser($this->Request); - } - - /** - * Test getUser method without code - * - * @return void - */ - public function testGetUserWithoutCode() - { - $this->Request = $this->Request->withQueryParams([ - 'state' => '__TEST_STATE__' - ]); - $this->Request->getSession()->write('oauth2state', '__TEST_STATE__'); - - $this->Provider->expects($this->never()) - ->method('getAuthorizationUrl'); - - $this->Provider->expects($this->never()) - ->method('getState'); - - $this->Provider->expects($this->never()) - ->method('getAccessToken'); - - $this->Provider->expects($this->never()) - ->method('getResourceOwner'); - - $this->expectException(BadRequestException::class); - $this->Service->getUser($this->Request); - } -} diff --git a/tests/TestCase/Social/Service/ServiceFactoryTest.php b/tests/TestCase/Social/Service/ServiceFactoryTest.php deleted file mode 100644 index 0fcc76d79..000000000 --- a/tests/TestCase/Social/Service/ServiceFactoryTest.php +++ /dev/null @@ -1,251 +0,0 @@ -Factory = new ServiceFactory(); - } - - /** - * Test createFromRequest method - * - * @return void - */ - public function testCreateFromRequest() - { - $config = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', - 'options' => [ - 'state' => '__TEST_STATE__', - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => '10003030300303', - 'clientSecret' => 'secretpassword' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]; - Configure::write('OAuth.providers.facebook', $config); - - $request = ServerRequestFactory::fromGlobals(); - $request = $request->withQueryParams([ - 'code' => 'ZPO9972j3092304230', - 'state' => '__TEST_STATE__' - ]); - $request = $request->withAttribute('params', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'provider' => 'facebook' - ]); - - $service = $this->Factory->createFromRequest($request); - $this->assertInstanceOf(OAuth2Service::class, $service); - $this->assertEquals('facebook', $service->getProviderName()); - - $expected = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', - 'options' => [ - 'state' => '__TEST_STATE__', - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'clientId' => '10003030300303', - 'clientSecret' => 'secretpassword' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]; - $actual = $service->getConfig(); - $this->assertEquals($expected, $actual); - } - - /** - * Test createFromRequest method - * - * @return void - */ - public function testCreateFromRequestCustomRedirectUriField() - { - $config = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', - 'options' => [ - 'state' => '__TEST_STATE__', - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/auth/facebook', - 'linkSocialUri' => '/link-social/facebook', - 'callbackLinkSocialUri' => '/callback-link-social/facebook', - 'clientId' => '10003030300303', - 'clientSecret' => 'secretpassword' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]; - Configure::write('OAuth.providers.facebook', $config); - - $request = ServerRequestFactory::fromGlobals(); - $request = $request->withQueryParams([ - 'code' => 'ZPO9972j3092304230', - 'state' => '__TEST_STATE__' - ]); - $request = $request->withAttribute('params', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'provider' => 'facebook' - ]); - - $this->Factory->setRedirectUriField('callbackLinkSocialUri'); - $service = $this->Factory->createFromRequest($request); - $this->assertInstanceOf(OAuth2Service::class, $service); - $this->assertEquals('facebook', $service->getProviderName()); - - $expected = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth2Service', - 'className' => 'League\OAuth2\Client\Provider\Facebook', - 'mapper' => 'CakeDC\Users\Social\Mapper\Facebook', - 'options' => [ - 'state' => '__TEST_STATE__', - 'graphApiVersion' => 'v2.8', - 'redirectUri' => '/callback-link-social/facebook', - 'clientId' => '10003030300303', - 'clientSecret' => 'secretpassword' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]; - $actual = $service->getConfig(); - $this->assertEquals($expected, $actual); - } - - /** - * Test createFromRequest method, with oauth1 - * - * @return void - */ - public function testCreateFromRequestOAuth1() - { - $config = [ - 'service' => 'CakeDC\Users\Social\Service\OAuth1Service', - 'className' => 'League\OAuth1\Client\Server\Twitter', - 'mapper' => 'CakeDC\Users\Social\Mapper\Twitter', - 'options' => [ - 'redirectUri' => '/auth/twitter', - 'linkSocialUri' => '/link-social/twitter', - 'callbackLinkSocialUri' => '/callback-link-social/twitter', - 'clientId' => '20003030300303', - 'clientSecret' => 'weakpassword' - ], - 'collaborators' => [], - 'signature' => null, - 'mapFields' => [], - 'path' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'prefix' => null - ] - ]; - Configure::write('OAuth.providers.twitter', $config); - - $request = ServerRequestFactory::fromGlobals(); - $request = $request->withAttribute('params', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'provider' => 'twitter' - ]); - - $actual = $this->Factory->createFromRequest($request); - $this->assertInstanceOf(OAuth1Service::class, $actual); - $this->assertEquals('twitter', $actual->getProviderName()); - } - - /** - * Test createFromRequest method, provider not enabled - * - * @return void - */ - public function testCreateFromRequestProviderNotEnabled() - { - $request = ServerRequestFactory::fromGlobals(); - $request = $request->withQueryParams([ - 'code' => 'ZPO9972j3092304230', - 'state' => '__TEST_STATE__' - ]); - $request = $request->withAttribute('params', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'socialLogin', - 'provider' => 'facebook' - ]); - - Configure::delete('OAuth.providers.facebook.options.redirectUri'); - Configure::delete('OAuth.providers.facebook.options.linkSocialUri'); - Configure::delete('OAuth.providers.facebook.options.callbackLinkSocialUri'); - Configure::write('OAuth.providers.facebook', []); - - $this->expectException(NotFoundException::class); - $this->Factory->createFromRequest($request); - } -} From 6a206614134f8156795e84c7b0ce6d9cc5bd21fd Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 19 Nov 2018 18:32:11 -0200 Subject: [PATCH 178/685] Moved policy namespace to auth plugin from users --- src/Plugin.php | 2 +- src/Policy/RbacPolicy.php | 24 --------- tests/TestCase/Policy/RbacPolicyTest.php | 64 ------------------------ 3 files changed, 1 insertion(+), 89 deletions(-) delete mode 100644 src/Policy/RbacPolicy.php delete mode 100644 tests/TestCase/Policy/RbacPolicyTest.php diff --git a/src/Plugin.php b/src/Plugin.php index 3b60b80e4..d66dc7fcc 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -12,11 +12,11 @@ use Authorization\Policy\OrmResolver; use Authorization\Policy\ResolverCollection; use CakeDC\Auth\Middleware\RbacMiddleware; +use CakeDC\Auth\Policy\RbacPolicy; use CakeDC\Users\Authentication\AuthenticationService; use CakeDC\Users\Middleware\OneTimePasswordAuthenticatorMiddleware; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; -use CakeDC\Users\Policy\RbacPolicy; use Cake\Core\BasePlugin; use Cake\Core\Configure; use Cake\Http\MiddlewareQueue; diff --git a/src/Policy/RbacPolicy.php b/src/Policy/RbacPolicy.php deleted file mode 100644 index c55a48f1a..000000000 --- a/src/Policy/RbacPolicy.php +++ /dev/null @@ -1,24 +0,0 @@ -getAttribute('rbac') ?? new Rbac(); - - $user = $identity ? $identity->getOriginalData()->toArray() : []; - - return (bool)$rbac->checkPermissions($user, $resource); - } -} diff --git a/tests/TestCase/Policy/RbacPolicyTest.php b/tests/TestCase/Policy/RbacPolicyTest.php deleted file mode 100644 index 5ca08b15a..000000000 --- a/tests/TestCase/Policy/RbacPolicyTest.php +++ /dev/null @@ -1,64 +0,0 @@ - '00000000-0000-0000-0000-000000000001', - 'password' => '12345' - ]); - $identity = new Identity($user); - $request = ServerRequestFactory::fromGlobals(); - $request = $request->withAttribute('identity', $identity); - $rbac = $this->getMockBuilder(Rbac::class)->setMethods(['checkPermissions'])->getMock(); - $request = $request->withAttribute('rbac', $rbac); - $rbac->expects($this->once()) - ->method('checkPermissions') - ->with( - $this->equalTo($identity->getOriginalData()->toArray()), - $this->equalTo($request) - ) - ->will($this->returnValue(true)); - $policy = new RbacPolicy(); - $this->assertTrue($policy->canAccess($identity, $request)); - } - - /** - * Test before method, with rbac returning false - */ - public function testBeforeRbacReturnedFalse() - { - $user = new User([ - 'id' => '00000000-0000-0000-0000-000000000001', - 'password' => '12345' - ]); - $identity = new Identity($user); - $request = ServerRequestFactory::fromGlobals(); - $request = $request->withAttribute('identity', $identity); - $rbac = $this->getMockBuilder(Rbac::class)->setMethods(['checkPermissions'])->getMock(); - $request = $request->withAttribute('rbac', $rbac); - $rbac->expects($this->once()) - ->method('checkPermissions') - ->with( - $this->equalTo($identity->getOriginalData()->toArray()), - $this->equalTo($request) - ) - ->will($this->returnValue(false)); - $request = $request->withAttribute('rbac', $rbac); - $policy = new RbacPolicy(); - $this->assertFalse($policy->canAccess($identity, $request)); - } -} From 5d3ff51f9617504d130c5ff96bc7d6cbbaa12f9c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 20 Nov 2018 14:21:47 -0200 Subject: [PATCH 179/685] Moved IsAuthorizedTrait to auth plugin --- src/Traits/IsAuthorizedTrait.php | 73 ------------------------------ src/View/Helper/AuthLinkHelper.php | 6 +-- 2 files changed, 3 insertions(+), 76 deletions(-) delete mode 100644 src/Traits/IsAuthorizedTrait.php diff --git a/src/Traits/IsAuthorizedTrait.php b/src/Traits/IsAuthorizedTrait.php deleted file mode 100644 index 75ed99129..000000000 --- a/src/Traits/IsAuthorizedTrait.php +++ /dev/null @@ -1,73 +0,0 @@ -checkRbacPermissions(Router::normalize(Router::reverse($url))); - } - - try { - //remove base from $url if exists - $normalizedUrl = Router::normalize($url); - - return $this->checkRbacPermissions($url); - } catch (MissingRouteException $ex) { - //if it's a url pointing to our own app - if (substr($normalizedUrl, 0, 1) === '/') { - throw $ex; - } - - return true; - } - } - - /** - * Check if current user permissions of url - * - * @param string $url to check permissions - * - * @return bool - */ - protected function checkRbacPermissions($url) - { - $uri = new Uri($url); - $Rbac = $this->request ? $this->request->getAttribute('rbac') : null; - if ($Rbac === null) { - $Rbac = new Rbac(); - } - $targetRequest = new ServerRequest([ - 'uri' => $uri - ]); - $params = Router::parseRequest($targetRequest); - $targetRequest = $targetRequest->withAttribute('params', $params); - - $user = $this->request->getAttribute('identity'); - $userData = []; - if ($user) { - $userData = $user->getOriginalData()->toArray(); - } - - return $Rbac->checkPermissions($userData, $targetRequest); - } -} diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index d30c3b0b3..30f2af04b 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -1,17 +1,17 @@ Date: Tue, 20 Nov 2018 14:43:37 -0200 Subject: [PATCH 180/685] Moved authentication/authorization namespaces to auth plugin --- config/users.php | 6 +- .../DefaultTwoFactorAuthenticationChecker.php | 43 --- .../TwoFactorAuthenticationCheckerFactory.php | 38 --- ...woFactorAuthenticationCheckerInterface.php | 30 -- src/Authentication/AuthenticationService.php | 123 -------- src/Authentication/Failure.php | 61 ---- src/Authentication/FailureInterface.php | 31 -- .../AuthenticatorFeedbackInterface.php | 15 - src/Authenticator/CookieAuthenticator.php | 46 --- src/Authenticator/FormAuthenticator.php | 149 --------- .../GoogleTwoFactorAuthenticator.php | 80 ----- src/Controller/Component/LoginComponent.php | 2 +- src/Controller/Traits/LoginTrait.php | 2 +- .../Traits/OneTimePasswordVerifyTrait.php | 2 +- ...OneTimePasswordAuthenticatorMiddleware.php | 42 --- src/Plugin.php | 6 +- ...aultTwoFactorAuthenticationCheckerTest.php | 66 ---- ...FactorAuthenticationCheckerFactoryTest.php | 43 --- .../AuthenticationServiceTest.php | 247 --------------- .../Authenticator/FormAuthenticatorTest.php | 289 ------------------ .../Controller/Traits/BaseTraitTest.php | 2 +- .../Controller/Traits/LoginTraitTest.php | 4 +- .../Controller/Traits/SocialTraitTest.php | 4 +- tests/TestCase/PluginTest.php | 20 +- 24 files changed, 24 insertions(+), 1327 deletions(-) delete mode 100644 src/Auth/DefaultTwoFactorAuthenticationChecker.php delete mode 100644 src/Auth/TwoFactorAuthenticationCheckerFactory.php delete mode 100644 src/Auth/TwoFactorAuthenticationCheckerInterface.php delete mode 100644 src/Authentication/AuthenticationService.php delete mode 100644 src/Authentication/Failure.php delete mode 100644 src/Authentication/FailureInterface.php delete mode 100644 src/Authenticator/AuthenticatorFeedbackInterface.php delete mode 100644 src/Authenticator/CookieAuthenticator.php delete mode 100644 src/Authenticator/FormAuthenticator.php delete mode 100644 src/Authenticator/GoogleTwoFactorAuthenticator.php delete mode 100644 src/Middleware/OneTimePasswordAuthenticatorMiddleware.php delete mode 100644 tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php delete mode 100644 tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php delete mode 100644 tests/TestCase/Authentication/AuthenticationServiceTest.php delete mode 100644 tests/TestCase/Authenticator/FormAuthenticatorTest.php diff --git a/config/users.php b/config/users.php index 2911144cd..4736527f4 100644 --- a/config/users.php +++ b/config/users.php @@ -145,7 +145,7 @@ 'skipGoogleVerify' => true, 'sessionKey' => 'Auth', ], - 'CakeDC/Users.Form' => [ + 'CakeDC/Auth.Form' => [ 'urlChecker' => 'Authentication.CakeRouter', 'loginUrl' => [ 'plugin' => 'CakeDC/Users', @@ -160,7 +160,7 @@ 'queryParam' => 'api_key', 'tokenPrefix' => null, ], - 'CakeDC/Users.Cookie' => [ + 'CakeDC/Auth.Cookie' => [ 'skipGoogleVerify' => true, 'rememberMeField' => 'remember_me', 'cookie' => [ @@ -242,7 +242,7 @@ 'messages' => [ 'FAILURE_INVALID_RECAPTCHA' => __d('CakeDC/Users', 'Invalid reCaptcha'), ], - 'targetAuthenticator' => 'CakeDC\Users\Authenticator\FormAuthenticator' + 'targetAuthenticator' => 'CakeDC\Auth\Authenticator\FormAuthenticator' ] ], 'SocialAuthMiddleware' => [ diff --git a/src/Auth/DefaultTwoFactorAuthenticationChecker.php b/src/Auth/DefaultTwoFactorAuthenticationChecker.php deleted file mode 100644 index 52a8435cc..000000000 --- a/src/Auth/DefaultTwoFactorAuthenticationChecker.php +++ /dev/null @@ -1,43 +0,0 @@ -isEnabled(); - } -} diff --git a/src/Auth/TwoFactorAuthenticationCheckerFactory.php b/src/Auth/TwoFactorAuthenticationCheckerFactory.php deleted file mode 100644 index caf849617..000000000 --- a/src/Auth/TwoFactorAuthenticationCheckerFactory.php +++ /dev/null @@ -1,38 +0,0 @@ -getSession()->write(self::GOOGLE_VERIFY_SESSION_KEY, $result->getData()); - - $result = new Result(null, self::NEED_GOOGLE_VERIFY); - - $this->_successfulAuthenticator = null; - $this->_result = $result; - - return compact('result', 'request', 'response'); - } - - /** - * Get the configured two factory authentication - * - * @return \CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface - */ - protected function getTwoFactorAuthenticationChecker() - { - return (new TwoFactorAuthenticationCheckerFactory())->build(); - } - - /** - * {@inheritDoc} - * - * @throws \RuntimeException Throws a runtime exception when no authenticators are loaded. - */ - public function authenticate(ServerRequestInterface $request, ResponseInterface $response) - { - if ($this->authenticators()->isEmpty()) { - throw new RuntimeException( - 'No authenticators loaded. You need to load at least one authenticator.' - ); - } - - $twoFaCheck = $this->getTwoFactorAuthenticationChecker(); - $this->failures = []; - $result = null; - foreach ($this->authenticators() as $authenticator) { - $result = $authenticator->authenticate($request, $response); - - if ($result->isValid()) { - $twoFaRequired = $twoFaCheck->isRequired($result->getData()->toArray()); - if ($twoFaRequired && $authenticator->getConfig('skipGoogleVerify') !== true) { - return $this->proceedToGoogleVerify($request, $response, $result); - } - - if (!($authenticator instanceof StatelessInterface)) { - $requestResponse = $this->persistIdentity($request, $response, $result->getData()); - $request = $requestResponse['request']; - $response = $requestResponse['response']; - } - - $this->_successfulAuthenticator = $authenticator; - $this->_result = $result; - - return [ - 'result' => $result, - 'request' => $request, - 'response' => $response - ]; - } else { - $this->failures[] = new Failure($authenticator, $result); - } - - if (!$result->isValid() && $authenticator instanceof StatelessInterface) { - $authenticator->unauthorizedChallenge($request); - } - } - - $this->_successfulAuthenticator = null; - $this->_result = $result; - - return [ - 'result' => $result, - 'request' => $request, - 'response' => $response - ]; - } - - /** - * Get list the list of failures processed - * - * @return Failure[] - */ - public function getFailures() - { - return $this->failures; - } -} diff --git a/src/Authentication/Failure.php b/src/Authentication/Failure.php deleted file mode 100644 index 40c5108da..000000000 --- a/src/Authentication/Failure.php +++ /dev/null @@ -1,61 +0,0 @@ -authenticator = $authenticator; - $this->result = $result; - } - - /** - * Returns failed authenticator. - * - * @return \Authentication\Authenticator\AuthenticatorInterface - */ - public function getAuthenticator() - { - return $this->authenticator; - } - - /** - * Returns failed result. - * - * @return \Authentication\Authenticator\ResultInterface - */ - public function getResult() - { - return $this->result; - } -} diff --git a/src/Authentication/FailureInterface.php b/src/Authentication/FailureInterface.php deleted file mode 100644 index 1edad8d9b..000000000 --- a/src/Authentication/FailureInterface.php +++ /dev/null @@ -1,31 +0,0 @@ -getConfig('rememberMeField'); - - $bodyData = $request->getParsedBody(); - if (empty($bodyData)) { - $session = $request->getAttribute('session'); - $bodyData = $session->read('CookieAuth'); - $session->delete('CookieAuth'); - } - - if (!$this->_checkUrl($request) || !is_array($bodyData) || empty($bodyData[$field])) { - return [ - 'request' => $request, - 'response' => $response - ]; - } - - $value = $this->_createToken($identity); - $cookie = $this->_createCookie($value); - - return [ - 'request' => $request, - 'response' => $response->withAddedHeader('Set-Cookie', $cookie->toHeaderValue()) - ]; - } -} diff --git a/src/Authenticator/FormAuthenticator.php b/src/Authenticator/FormAuthenticator.php deleted file mode 100644 index 91e0b8434..000000000 --- a/src/Authenticator/FormAuthenticator.php +++ /dev/null @@ -1,149 +0,0 @@ -identifier = $identifier; - $this->config = $config; - } - - /** - * Gets the actual base authenticator - * - * @return \Authentication\Authenticator\FormAuthenticator - */ - protected function getBaseAuthenticator() - { - if ($this->baseAuthenticator === null) { - $this->baseAuthenticator = $this->createBaseAuthenticator($this->identifier, $this->config); - } - - return $this->baseAuthenticator; - } - - /** - * Create the base authenticator - * - * @param \Authentication\Identifier\IdentifierInterface $identifier Identifier or identifiers collection. - * @param array $config Configuration settings. - * - * @return \Authentication\Authenticator\AuthenticatorInterface - */ - protected function createBaseAuthenticator(IdentifierInterface $identifier, array $config = []) - { - if (!isset($config['baseClassName'])) { - return new BaseFormAuthenticator($identifier, $config); - } - - $className = $config['baseClassName']; - unset($config['baseClassName']); - if (!class_exists($className)) { - throw new \InvalidArgumentException(__("Base class for FormAuthenticator {0} does not exist", $className)); - } - - return new $className($identifier, $config); - } - - /** - * Get the last result of authenticator - * - * @return Result|null - */ - public function getLastResult() - { - return $this->lastResult; - } - - /** - * Authenticates the identity contained in a request. Wrapper for Authentication\Authenticator\FormAuthenticator - * to also check reCaptcha. Will use the `config.userModel`, and `config.fields` - * to find POST data that is used to find a matching record in the `config.userModel`. Will return false if - * there is no post data, either username or password is missing, or if the scope conditions have not been met. - * - * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. - * @param \Psr\Http\Message\ResponseInterface $response Unused response object. - * @return \Authentication\Authenticator\ResultInterface - */ - public function authenticate(ServerRequestInterface $request, ResponseInterface $response) - { - $result = $this->getBaseAuthenticator()->authenticate($request, $response); - if (!Configure::read('Users.reCaptcha.login') || in_array($result->getStatus(), [Result::FAILURE_OTHER, Result::FAILURE_CREDENTIALS_MISSING])) { - return $this->lastResult = $result; - } - - $data = $request->getParsedBody(); - $captcha = $data['g-recaptcha-response'] ? $data['g-recaptcha-response'] : null; - - $valid = $this->validateReCaptcha( - $captcha, - $request->clientIp() - ); - - if ($valid) { - return $this->lastResult = $result; - } - - return $this->lastResult = new Result(null, self::FAILURE_INVALID_RECAPTCHA); - } - - /** - * Call base authenticator methods - * - * @param string $name base authentication method name - * @param array $arguments used in base authenticator method - * @return mixed - */ - public function __call($name, $arguments) - { - return $this->getBaseAuthenticator()->$name(...$arguments); - } -} diff --git a/src/Authenticator/GoogleTwoFactorAuthenticator.php b/src/Authenticator/GoogleTwoFactorAuthenticator.php deleted file mode 100644 index 061adda8c..000000000 --- a/src/Authenticator/GoogleTwoFactorAuthenticator.php +++ /dev/null @@ -1,80 +0,0 @@ - null, - 'urlChecker' => 'Authentication.Default', - ]; - - /** - * Prepares the error object for a login URL error - * - * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. - * @return \Authentication\Authenticator\ResultInterface - */ - protected function _buildLoginUrlErrorResult($request) - { - $errors = [ - sprintf( - 'Login URL `%s` did not match `%s`.', - (string)$request->getUri(), - implode('` or `', (array)$this->getConfig('loginUrl')) - ) - ]; - - return new Result(null, Result::FAILURE_OTHER, $errors); - } - - /** - * Authenticates the identity contained in a request. Will use the `config.userModel`, and `config.fields` - * to find POST data that is used to find a matching record in the `config.userModel`. Will return false if - * there is no post data, either username or password is missing, or if the scope conditions have not been met. - * - * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. - * @param \Psr\Http\Message\ResponseInterface $response Unused response object. - * @return \Authentication\Authenticator\ResultInterface - */ - public function authenticate(ServerRequestInterface $request, ResponseInterface $response) - { - if (!$this->_checkUrl($request)) { - return $this->_buildLoginUrlErrorResult($request); - } - - $data = $request->getSession()->read('GoogleTwoFactor.User'); - - if ($data === null) { - return new Result(null, Result::FAILURE_CREDENTIALS_MISSING, [ - 'Login credentials not found' - ]); - } - - $request->getSession()->delete('GoogleTwoFactor.User'); - - return new Result($data, Result::SUCCESS); - } -} diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index 311ca4353..8796c4a2d 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -2,7 +2,7 @@ namespace CakeDC\Users\Controller\Component; use Authentication\Authenticator\ResultInterface; -use CakeDC\Users\Authentication\AuthenticationService; +use CakeDC\Auth\Authentication\AuthenticationService; use CakeDC\Users\Plugin; use Cake\Controller\Component; diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index edf788c1e..0df018e6f 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -11,7 +11,7 @@ namespace CakeDC\Users\Controller\Traits; -use CakeDC\Users\Authentication\AuthenticationService; +use CakeDC\Auth\Authentication\AuthenticationService; use CakeDC\Users\Plugin; use Cake\Core\Configure; use Cake\Http\Exception\NotFoundException; diff --git a/src/Controller/Traits/OneTimePasswordVerifyTrait.php b/src/Controller/Traits/OneTimePasswordVerifyTrait.php index 8ba57d8d0..c32184779 100644 --- a/src/Controller/Traits/OneTimePasswordVerifyTrait.php +++ b/src/Controller/Traits/OneTimePasswordVerifyTrait.php @@ -2,7 +2,7 @@ namespace CakeDC\Users\Controller\Traits; -use CakeDC\Users\Authentication\AuthenticationService; +use CakeDC\Auth\Authentication\AuthenticationService; use Cake\Core\Configure; trait OneTimePasswordVerifyTrait diff --git a/src/Middleware/OneTimePasswordAuthenticatorMiddleware.php b/src/Middleware/OneTimePasswordAuthenticatorMiddleware.php deleted file mode 100644 index f976a3ba1..000000000 --- a/src/Middleware/OneTimePasswordAuthenticatorMiddleware.php +++ /dev/null @@ -1,42 +0,0 @@ -getAttribute('authentication'); - - if (!$service->getResult() || $service->getResult()->getStatus() !== AuthenticationService::NEED_GOOGLE_VERIFY) { - return $next($request, $response); - } - - $request->getSession()->write('CookieAuth', [ - 'remember_me' => $request->getData('remember_me') - ]); - - $url = Router::url([ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'verify' - ]); - - return $response - ->withHeader('Location', $url) - ->withStatus(302); - } -} diff --git a/src/Plugin.php b/src/Plugin.php index d66dc7fcc..7f0dd7e0d 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -11,10 +11,10 @@ use Authorization\Policy\MapResolver; use Authorization\Policy\OrmResolver; use Authorization\Policy\ResolverCollection; +use CakeDC\Auth\Authentication\AuthenticationService; +use CakeDC\Auth\Middleware\OneTimePasswordAuthenticatorMiddleware; use CakeDC\Auth\Middleware\RbacMiddleware; use CakeDC\Auth\Policy\RbacPolicy; -use CakeDC\Users\Authentication\AuthenticationService; -use CakeDC\Users\Middleware\OneTimePasswordAuthenticatorMiddleware; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; use Cake\Core\BasePlugin; @@ -109,7 +109,7 @@ public function authentication() } if (Configure::read('Users.OneTimePasswordAuthenticator.login')) { - $service->loadAuthenticator('CakeDC/Users.GoogleTwoFactor', [ + $service->loadAuthenticator('CakeDC/Auth.TwoFactor', [ 'skipGoogleVerify' => true, ]); } diff --git a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php b/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php deleted file mode 100644 index 71ad48bb0..000000000 --- a/tests/TestCase/Auth/DefaultTwoFactorAuthenticationCheckerTest.php +++ /dev/null @@ -1,66 +0,0 @@ -assertFalse($Checker->isEnabled()); - - Configure::write('Users.OneTimePasswordAuthenticator.login', true); - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertTrue($Checker->isEnabled()); - - Configure::delete('Users.OneTimePasswordAuthenticator.login'); - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertTrue($Checker->isEnabled()); - } - - /** - * Test isRequired method - * - * @return void - */ - public function testIsRequired() - { - Configure::write('Users.OneTimePasswordAuthenticator.login', false); - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertFalse($Checker->isRequired(['id' => 10])); - - Configure::write('Users.OneTimePasswordAuthenticator.login', true); - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertTrue($Checker->isRequired(['id' => 10])); - - Configure::delete('Users.OneTimePasswordAuthenticator.login'); - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertTrue($Checker->isRequired(['id' => 10])); - - $Checker = new DefaultTwoFactorAuthenticationChecker(); - $this->assertFalse($Checker->isRequired([])); - } -} diff --git a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php b/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php deleted file mode 100644 index 2a5e6957e..000000000 --- a/tests/TestCase/Auth/TwoFactorAuthenticationCheckerFactoryTest.php +++ /dev/null @@ -1,43 +0,0 @@ -build(); - $this->assertInstanceOf(DefaultTwoFactorAuthenticationChecker::class, $result); - } - - /** - * Test getChecker method - * - * @return void - */ - public function testGetCheckerInvalidInterface() - { - Configure::write('OneTimePasswordAuthenticator.checker', 'stdClass'); - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage("Invalid config for 'OneTimePasswordAuthenticator.checker', 'stdClass' does not implement 'CakeDC\Users\Auth\TwoFactorAuthenticationCheckerInterface'"); - (new TwoFactorAuthenticationCheckerFactory())->build(); - } -} diff --git a/tests/TestCase/Authentication/AuthenticationServiceTest.php b/tests/TestCase/Authentication/AuthenticationServiceTest.php deleted file mode 100644 index 575086b2b..000000000 --- a/tests/TestCase/Authentication/AuthenticationServiceTest.php +++ /dev/null @@ -1,247 +0,0 @@ -get('CakeDC/Users.Users'); - $entity = $Table->get('00000000-0000-0000-0000-000000000001'); - $entity->password = 'password'; - $this->assertTrue((bool)$Table->save($entity)); - $request = ServerRequestFactory::fromGlobals( - ['REQUEST_URI' => '/testpath'], - [], - ['username' => 'user-not-found', 'password' => 'password'] - ); - $response = new Response(); - - $service = new AuthenticationService([ - 'identifiers' => [ - 'Authentication.Password' - ], - 'authenticators' => [ - 'Authentication.Session', - 'CakeDC/Users.Form' - ] - ]); - - $result = $service->authenticate($request, $response); - $this->assertInstanceOf(Result::class, $result['result']); - $this->assertInstanceOf(ServerRequestInterface::class, $result['request']); - $this->assertInstanceOf(ResponseInterface::class, $result['response']); - $this->assertFalse($result['result']->isValid()); - $result = $service->getAuthenticationProvider(); - $this->assertNull($result); - $this->assertNull( - $request->getAttribute('session')->read('Auth') - ); - $this->assertEmpty($response->getHeaderLine('Location')); - $this->assertNull($response->getStatusCode()); - - $sessionFailure = new Failure( - $service->authenticators()->get('Session'), - new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) - ); - $formFailure = new Failure( - $service->authenticators()->get('Form'), - new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND, [ - 'Password' => [] - ]) - ); - $expected = [$sessionFailure, $formFailure]; - $actual = $service->getFailures(); - $this->assertEquals($expected, $actual); - } - - /** - * testAuthenticate - * - * @return void - */ - public function testAuthenticate() - { - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $entity = $Table->get('00000000-0000-0000-0000-000000000001'); - $entity->password = 'password'; - $this->assertTrue((bool)$Table->save($entity)); - $request = ServerRequestFactory::fromGlobals( - ['REQUEST_URI' => '/testpath'], - [], - ['username' => 'user-1', 'password' => 'password'] - ); - $response = new Response(); - - $service = new AuthenticationService([ - 'identifiers' => [ - 'Authentication.Password' - ], - 'authenticators' => [ - 'Authentication.Session', - 'CakeDC/Users.Form' - ] - ]); - - $result = $service->authenticate($request, $response); - $this->assertInstanceOf(Result::class, $result['result']); - $this->assertInstanceOf(ServerRequestInterface::class, $result['request']); - $this->assertInstanceOf(ResponseInterface::class, $result['response']); - - $this->assertTrue($result['result']->isValid()); - - $result = $service->getAuthenticationProvider(); - $this->assertInstanceOf(FormAuthenticator::class, $result); - - $this->assertEquals( - 'user-1', - $request->getAttribute('session')->read('Auth.username') - ); - $this->assertEmpty($response->getHeaderLine('Location')); - $this->assertNull($response->getStatusCode()); - - $sessionFailure = new Failure( - $service->authenticators()->get('Session'), - new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) - ); - $expected = [$sessionFailure]; - $actual = $service->getFailures(); - $this->assertEquals($expected, $actual); - } - - /** - * testAuthenticate - * - * @return void - */ - public function testAuthenticateShouldDoGoogleVerifyEnabled() - { - Configure::write('Users.OneTimePasswordAuthenticator.login', true); - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $entity = $Table->get('00000000-0000-0000-0000-000000000001'); - $entity->password = 'password'; - $this->assertTrue((bool)$Table->save($entity)); - $request = ServerRequestFactory::fromGlobals( - ['REQUEST_URI' => '/testpath'], - [], - ['username' => 'user-1', 'password' => 'password'] - ); - $response = new Response(); - - $service = new AuthenticationService([ - 'identifiers' => [ - 'Authentication.Password' => [] - ], - 'authenticators' => [ - 'Authentication.Session' => [ - 'skipGoogleVerify' => true, - ], - 'CakeDC/Users.Form' => [ - 'skipGoogleVerify' => false, - ] - ] - ]); - - $result = $service->authenticate($request, $response); - $this->assertInstanceOf(Result::class, $result['result']); - $this->assertInstanceOf(ServerRequestInterface::class, $result['request']); - $this->assertInstanceOf(ResponseInterface::class, $result['response']); - $this->assertFalse($result['result']->isValid()); - $this->assertEquals(AuthenticationService::NEED_GOOGLE_VERIFY, $result['result']->getStatus()); - $this->assertNull($request->getAttribute('session')->read('Auth.username')); - $this->assertEquals( - 'user-1', - $request->getAttribute('session')->read('temporarySession.username') - ); - $sessionFailure = new Failure( - $service->authenticators()->get('Session'), - new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) - ); - $expected = [$sessionFailure]; - $actual = $service->getFailures(); - $this->assertEquals($expected, $actual); - } - - /** - * testAuthenticate - * - * @return void - */ - public function testAuthenticateShouldDoGoogleVerifyDisabled() - { - Configure::write('Users.OneTimePasswordAuthenticator.login', false); - $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $entity = $Table->get('00000000-0000-0000-0000-000000000001'); - $entity->password = 'password'; - $this->assertTrue((bool)$Table->save($entity)); - $request = ServerRequestFactory::fromGlobals( - ['REQUEST_URI' => '/testpath'], - [], - ['username' => 'user-1', 'password' => 'password'] - ); - $response = new Response(); - - $service = new AuthenticationService([ - 'identifiers' => [ - 'Authentication.Password' => [] - ], - 'authenticators' => [ - 'Authentication.Session' => [ - 'skipGoogleVerify' => true, - ], - 'CakeDC/Users.Form' => [ - 'skipGoogleVerify' => false, - ] - ] - ]); - - $result = $service->authenticate($request, $response); - $this->assertInstanceOf(Result::class, $result['result']); - $this->assertInstanceOf(ServerRequestInterface::class, $result['request']); - $this->assertInstanceOf(ResponseInterface::class, $result['response']); - - $this->assertTrue($result['result']->isValid()); - - $result = $service->getAuthenticationProvider(); - $this->assertInstanceOf(FormAuthenticator::class, $result); - - $this->assertEquals( - 'user-1', - $request->getAttribute('session')->read('Auth.username') - ); - $this->assertEmpty($response->getHeaderLine('Location')); - $this->assertNull($response->getStatusCode()); - $sessionFailure = new Failure( - $service->authenticators()->get('Session'), - new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND) - ); - $expected = [$sessionFailure]; - $actual = $service->getFailures(); - $this->assertEquals($expected, $actual); - } -} diff --git a/tests/TestCase/Authenticator/FormAuthenticatorTest.php b/tests/TestCase/Authenticator/FormAuthenticatorTest.php deleted file mode 100644 index b0c3f4862..000000000 --- a/tests/TestCase/Authenticator/FormAuthenticatorTest.php +++ /dev/null @@ -1,289 +0,0 @@ -getMockBuilder(\Authentication\Authenticator\FormAuthenticator::class) - ->setConstructorArgs([$identifiers]) - ->setMethods(['authenticate']) - ->getMock(); - $request = ServerRequestFactory::fromGlobals( - ['REQUEST_URI' => '/testpath'], - [], - ['username' => 'marcelo', 'password' => 'password', 'g-recaptcha-response' => 'BD-S2333-156465897897'] - ); - $response = new Response(); - - $baseResult = new Result( - null, - Result::FAILURE_OTHER - ); - $BaseAuthenticator->expects($this->once()) - ->method('authenticate') - ->with($request, $response) - ->will($this->returnValue($baseResult)); - - $Authenticator = $this->getMockBuilder(FormAuthenticator::class)->setConstructorArgs([ - $identifiers, - [ - 'fields' => [ - IdentifierInterface::CREDENTIAL_USERNAME => 'email', - IdentifierInterface::CREDENTIAL_PASSWORD => 'password' - ] - ] - ])->setMethods(['createBaseAuthenticator', 'validateReCaptcha'])->getMock(); - - Configure::write('Users.reCaptcha.login', true); - $Authenticator->expects($this->once()) - ->method('createBaseAuthenticator') - ->with( - $this->equalTo($identifiers), - $this->equalTo([ - 'fields' => [ - IdentifierInterface::CREDENTIAL_USERNAME => 'email', - IdentifierInterface::CREDENTIAL_PASSWORD => 'password' - ] - ]) - )->will($this->returnValue($BaseAuthenticator)); - - $Authenticator->expects($this->never()) - ->method('validateReCaptcha'); - - $result = $Authenticator->authenticate($request, $response); - $this->assertInstanceOf(Result::class, $result); - $this->assertEquals(Result::FAILURE_OTHER, $result->getStatus()); - $this->assertSame($baseResult, $result); - $this->assertSame($baseResult, $Authenticator->getLastResult()); - } - - /** - * testAuthenticate - * - * @return void - */ - public function testAuthenticate() - { - $identifiers = new IdentifierCollection([ - 'Authentication.Password' - ]); - - $BaseAuthenticator = $this->getMockBuilder(\Authentication\Authenticator\FormAuthenticator::class) - ->setConstructorArgs([$identifiers]) - ->setMethods(['authenticate']) - ->getMock(); - $request = ServerRequestFactory::fromGlobals( - ['REQUEST_URI' => '/testpath'], - [], - ['username' => 'marcelo', 'password' => 'password', 'g-recaptcha-response' => 'BD-S2333-156465897897'] - ); - $response = new Response(); - - $baseResult = new Result( - [ - 'id' => '42', - 'username' => 'marcelo', - 'role' => 'user' - ], - Result::SUCCESS - ); - $BaseAuthenticator->expects($this->once()) - ->method('authenticate') - ->with($request, $response) - ->will($this->returnValue($baseResult)); - - $Authenticator = $this->getMockBuilder(FormAuthenticator::class)->setConstructorArgs([ - $identifiers, - [ - 'fields' => [ - IdentifierInterface::CREDENTIAL_USERNAME => 'email', - IdentifierInterface::CREDENTIAL_PASSWORD => 'password' - ] - ] - ])->setMethods(['createBaseAuthenticator', 'validateReCaptcha'])->getMock(); - - Configure::write('Users.reCaptcha.login', true); - $Authenticator->expects($this->once()) - ->method('createBaseAuthenticator') - ->with( - $this->equalTo($identifiers), - $this->equalTo([ - 'fields' => [ - IdentifierInterface::CREDENTIAL_USERNAME => 'email', - IdentifierInterface::CREDENTIAL_PASSWORD => 'password' - ] - ]) - )->will($this->returnValue($BaseAuthenticator)); - - $Authenticator->expects($this->once()) - ->method('validateReCaptcha') - ->with( - $this->equalTo('BD-S2333-156465897897') - ) - ->will($this->returnValue(true)); - - $result = $Authenticator->authenticate($request, $response); - $this->assertInstanceOf(Result::class, $result); - $this->assertEquals(Result::SUCCESS, $result->getStatus()); - $this->assertSame($baseResult, $result); - $this->assertSame($baseResult, $Authenticator->getLastResult()); - } - - /** - * testAuthenticate - * - * @return void - */ - public function testAuthenticateNotRequiredReCaptcha() - { - $identifiers = new IdentifierCollection([ - 'Authentication.Password' - ]); - - $BaseAuthenticator = $this->getMockBuilder(\Authentication\Authenticator\FormAuthenticator::class) - ->setConstructorArgs([$identifiers]) - ->setMethods(['authenticate']) - ->getMock(); - $request = ServerRequestFactory::fromGlobals( - ['REQUEST_URI' => '/testpath'], - [], - ['username' => 'marcelo', 'password' => 'password', 'g-recaptcha-response' => 'BD-S2333-156465897897'] - ); - $response = new Response(); - - $baseResult = new Result( - [ - 'id' => '42', - 'username' => 'marcelo', - 'role' => 'user' - ], - Result::SUCCESS - ); - $BaseAuthenticator->expects($this->once()) - ->method('authenticate') - ->with($request, $response) - ->will($this->returnValue($baseResult)); - - $Authenticator = $this->getMockBuilder(FormAuthenticator::class)->setConstructorArgs([ - $identifiers, - [ - 'fields' => [ - IdentifierInterface::CREDENTIAL_USERNAME => 'email', - IdentifierInterface::CREDENTIAL_PASSWORD => 'password' - ] - ] - ])->setMethods(['createBaseAuthenticator', 'validateReCaptcha'])->getMock(); - - Configure::write('Users.reCaptcha.login', false); - $Authenticator->expects($this->once()) - ->method('createBaseAuthenticator') - ->with( - $this->equalTo($identifiers), - $this->equalTo([ - 'fields' => [ - IdentifierInterface::CREDENTIAL_USERNAME => 'email', - IdentifierInterface::CREDENTIAL_PASSWORD => 'password' - ] - ]) - )->will($this->returnValue($BaseAuthenticator)); - - $Authenticator->expects($this->never()) - ->method('validateReCaptcha'); - - $result = $Authenticator->authenticate($request, $response); - $this->assertInstanceOf(Result::class, $result); - $this->assertEquals(Result::SUCCESS, $result->getStatus()); - $this->assertSame($baseResult, $result); - $this->assertSame($baseResult, $Authenticator->getLastResult()); - } - - /** - * testAuthenticate - * - * @return void - */ - public function testAuthenticateInvalidRecaptcha() - { - $identifiers = new IdentifierCollection([ - 'Authentication.Password' - ]); - - $BaseAuthenticator = $this->getMockBuilder(\Authentication\Authenticator\FormAuthenticator::class) - ->setConstructorArgs([$identifiers]) - ->setMethods(['authenticate']) - ->getMock(); - $request = ServerRequestFactory::fromGlobals( - ['REQUEST_URI' => '/testpath'], - [], - ['username' => 'marcelo', 'password' => 'password', 'g-recaptcha-response' => 'BD-S2333-156465897897'] - ); - $response = new Response(); - - $baseResult = new Result( - [ - 'id' => '42', - 'username' => 'marcelo', - 'role' => 'user' - ], - Result::SUCCESS - ); - $BaseAuthenticator->expects($this->once()) - ->method('authenticate') - ->with($request, $response) - ->will($this->returnValue($baseResult)); - - $Authenticator = $this->getMockBuilder(FormAuthenticator::class)->setConstructorArgs([ - $identifiers, - [ - 'fields' => [ - IdentifierInterface::CREDENTIAL_USERNAME => 'email', - IdentifierInterface::CREDENTIAL_PASSWORD => 'password' - ] - ] - ])->setMethods(['createBaseAuthenticator', 'validateReCaptcha'])->getMock(); - - Configure::write('Users.reCaptcha.login', true); - $Authenticator->expects($this->once()) - ->method('createBaseAuthenticator') - ->with( - $this->equalTo($identifiers), - $this->equalTo([ - 'fields' => [ - IdentifierInterface::CREDENTIAL_USERNAME => 'email', - IdentifierInterface::CREDENTIAL_PASSWORD => 'password' - ] - ]) - )->will($this->returnValue($BaseAuthenticator)); - - $Authenticator->expects($this->once()) - ->method('validateReCaptcha') - ->with( - $this->equalTo('BD-S2333-156465897897') - ) - ->will($this->returnValue(false)); - - $result = $Authenticator->authenticate($request, $response); - $this->assertInstanceOf(Result::class, $result); - $this->assertEquals(FormAuthenticator::FAILURE_INVALID_RECAPTCHA, $result->getStatus()); - $this->assertNull($result->getData()); - $this->assertSame($result, $Authenticator->getLastResult()); - } -} diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index 74f830693..1282ff34c 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -14,7 +14,7 @@ use Authentication\Authenticator\Result; use Authentication\Controller\Component\AuthenticationComponent; use Authentication\Identity; -use CakeDC\Users\Authentication\AuthenticationService; +use CakeDC\Auth\Authentication\AuthenticationService; use CakeDC\Users\Model\Entity\User; use Cake\Controller\ComponentRegistry; use Cake\Controller\Controller; diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 3e854d420..4c18430c3 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -14,8 +14,8 @@ use Authentication\Authenticator\Result; use Authentication\Authenticator\SessionAuthenticator; use Authentication\Identifier\IdentifierCollection; -use CakeDC\Users\Authentication\Failure; -use CakeDC\Users\Authenticator\FormAuthenticator; +use CakeDC\Auth\Authentication\Failure; +use CakeDC\Auth\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Controller\Component\LoginComponent; use Cake\Controller\ComponentRegistry; diff --git a/tests/TestCase/Controller/Traits/SocialTraitTest.php b/tests/TestCase/Controller/Traits/SocialTraitTest.php index 86b7de025..734d57282 100644 --- a/tests/TestCase/Controller/Traits/SocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/SocialTraitTest.php @@ -14,8 +14,8 @@ use Authentication\Authenticator\Result; use Authentication\Authenticator\SessionAuthenticator; use Authentication\Identifier\IdentifierCollection; -use CakeDC\Users\Authentication\Failure; -use CakeDC\Users\Authenticator\FormAuthenticator; +use CakeDC\Auth\Authentication\Failure; +use CakeDC\Auth\Authenticator\FormAuthenticator; use CakeDC\Users\Authenticator\SocialAuthenticator; use CakeDC\Users\Controller\Component\LoginComponent; use Cake\Controller\ComponentRegistry; diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index af8b3a45b..f5989ffd1 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -12,11 +12,11 @@ use Authorization\Middleware\AuthorizationMiddleware; use Authorization\Middleware\RequestAuthorizationMiddleware; use Authorization\Policy\ResolverCollection; +use CakeDC\Auth\Authentication\AuthenticationService as CakeDCAuthenticationService; +use CakeDC\Auth\Authenticator\FormAuthenticator; +use CakeDC\Auth\Authenticator\TwoFactorAuthenticator; +use CakeDC\Auth\Middleware\OneTimePasswordAuthenticatorMiddleware; use CakeDC\Auth\Middleware\RbacMiddleware; -use CakeDC\Users\Authentication\AuthenticationService as CakeDCAuthenticationService; -use CakeDC\Users\Authenticator\FormAuthenticator; -use CakeDC\Users\Authenticator\GoogleTwoFactorAuthenticator; -use CakeDC\Users\Middleware\OneTimePasswordAuthenticatorMiddleware; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; use CakeDC\Users\Plugin; @@ -248,7 +248,7 @@ public function testGetAuthenticationService() 'fields' => ['username' => 'email'], 'identify' => true, ], - 'CakeDC/Users.Form' => [ + 'CakeDC/Auth.Form' => [ 'loginUrl' => '/login', 'fields' => ['username' => 'email', 'password' => 'alt_password'], ], @@ -291,7 +291,7 @@ public function testGetAuthenticationService() ], FormAuthenticator::class => [ 'loginUrl' => '/login', - 'urlChecker' => 'Authentication.Default', + 'keyCheckEnabledRecaptcha' => 'Users.reCaptcha.login', 'fields' => ['username' => 'email', 'password' => 'alt_password'] ], TokenAuthenticator::class => [ @@ -300,7 +300,7 @@ public function testGetAuthenticationService() 'tokenPrefix' => null, 'skipGoogleVerify' => true ], - GoogleTwoFactorAuthenticator::class => [ + TwoFactorAuthenticator::class => [ 'loginUrl' => null, 'urlChecker' => 'Authentication.Default', 'skipGoogleVerify' => true @@ -357,7 +357,7 @@ public function testGetAuthenticationServiceWithouOneTimePasswordAuthenticator() 'fields' => ['username' => 'email'], 'identify' => true, ], - 'CakeDC/Users.Form' => [ + 'CakeDC/Auth.Form' => [ 'loginUrl' => '/login', 'fields' => ['username' => 'email', 'password' => 'alt_password'], ], @@ -395,8 +395,8 @@ public function testGetAuthenticationServiceWithouOneTimePasswordAuthenticator() ], FormAuthenticator::class => [ 'loginUrl' => '/login', - 'urlChecker' => 'Authentication.Default', - 'fields' => ['username' => 'email', 'password' => 'alt_password'] + 'fields' => ['username' => 'email', 'password' => 'alt_password'], + 'keyCheckEnabledRecaptcha' => 'Users.reCaptcha.login' ], TokenAuthenticator::class => [ 'header' => null, From 98c3b69fa584a73e97ebfa0e13d26529a6b740c3 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 20 Nov 2018 14:51:33 -0200 Subject: [PATCH 181/685] Social Authenticator extending class from auth plugin --- src/Authenticator/SocialAuthenticator.php | 101 +--------------------- 1 file changed, 2 insertions(+), 99 deletions(-) diff --git a/src/Authenticator/SocialAuthenticator.php b/src/Authenticator/SocialAuthenticator.php index 88426a484..b39fa577b 100644 --- a/src/Authenticator/SocialAuthenticator.php +++ b/src/Authenticator/SocialAuthenticator.php @@ -2,117 +2,20 @@ namespace CakeDC\Users\Authenticator; -use Authentication\Authenticator\AbstractAuthenticator; -use Authentication\Authenticator\Result; use Authentication\UrlChecker\UrlCheckerTrait; -use CakeDC\Auth\Social\MapUser; -use CakeDC\Auth\Social\Service\ServiceInterface; -use CakeDC\Users\Exception\SocialAuthenticationException; -use Cake\Http\Exception\BadRequestException; -use Cake\Log\LogTrait; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; +use CakeDC\Auth\Authenticator\SocialAuthenticator as BaseAuthenticator; /** * Social authenticator * * Authenticates an identity based on request attribute socialService (CakeDC\Auth\Social\Service\ServiceInterface) */ -class SocialAuthenticator extends AbstractAuthenticator +class SocialAuthenticator extends BaseAuthenticator { - use LogTrait; use SocialAuthTrait; use UrlCheckerTrait; - const SOCIAL_SERVICE_ATTRIBUTE = 'socialService'; - const FAILURE_ACCOUNT_NOT_ACTIVE = 'FAILURE_ACCOUNT_NOT_ACTIVE'; const FAILURE_USER_NOT_ACTIVE = 'FAILURE_USER_NOT_ACTIVE'; - /** - * Default config for this object. - * - `fields` The fields to use to identify a user by. - * - `loginUrl` Login URL or an array of URLs. - * - `urlChecker` Url checker config. - * - * @var array - */ - protected $_defaultConfig = []; - - /** - * Authenticates the identity contained in a request. Will use the `config.userModel`, and `config.fields` - * to find POST data that is used to find a matching record in the `config.userModel`. Will return false if - * there is no post data, either username or password is missing, or if the scope conditions have not been met. - * - * @param \Psr\Http\Message\ServerRequestInterface $request The request that contains login information. - * @param \Psr\Http\Message\ResponseInterface $response Unused response object. - * @throws \Exception - * @throws SocialAuthenticationException - * @return \Authentication\Authenticator\ResultInterface - */ - /** - * @param ServerRequestInterface $request the cake request. - * @param ResponseInterface $response the cake response. - * @return Result|\Authentication\Authenticator\ResultInterface - * @throws \Exception - */ - public function authenticate(ServerRequestInterface $request, ResponseInterface $response) - { - $service = $request->getAttribute(self::SOCIAL_SERVICE_ATTRIBUTE); - if ($service === null) { - return new Result(null, Result::FAILURE_CREDENTIALS_MISSING); - } - - $rawData = $this->getRawData($request, $service); - if (empty($rawData)) { - return new Result(null, Result::FAILURE_IDENTITY_NOT_FOUND); - } - - return $this->identify($rawData); - } - - /** - * Get user raw data from social provider - * - * @param ServerRequestInterface $request request object - * @param ServiceInterface $service social service - * @throws \Exception - * @return array|null - */ - private function getRawData(ServerRequestInterface $request, ServiceInterface $service) - { - $rawData = null; - try { - $rawData = $service->getUser($request); - - return (new MapUser())($service, $rawData); - } catch (\Exception $exception) { - $list = [BadRequestException::class, \UnexpectedValueException::class]; - $this->throwIfNotInlist($exception, $list); - $message = sprintf( - "Error getting an access token / retrieving the authorized user's profile data. Error message: %s %s", - $exception->getMessage(), - $exception - ); - $this->log($message); - - return null; - } - } - - /** - * Throw the exception if not in the list - * - * @param \Exception $exception exception thrown - * @param array $list list of allowed exception classes - * @throws \Exception - * @return void - */ - private function throwIfNotInlist(\Exception $exception, array $list) - { - $className = get_class($exception); - if (!in_array($className, $list)) { - throw $exception; - } - } } From a86aa81a26ef0c8df7ad6e6fc786da326acde1a5 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 20 Nov 2018 14:52:12 -0200 Subject: [PATCH 182/685] update file header --- src/Authenticator/SocialAuthenticator.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Authenticator/SocialAuthenticator.php b/src/Authenticator/SocialAuthenticator.php index b39fa577b..d71db89c7 100644 --- a/src/Authenticator/SocialAuthenticator.php +++ b/src/Authenticator/SocialAuthenticator.php @@ -1,4 +1,13 @@ Date: Tue, 20 Nov 2018 14:57:23 -0200 Subject: [PATCH 183/685] fixing configuration --- config/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index 4736527f4..68708bea8 100644 --- a/config/users.php +++ b/config/users.php @@ -114,7 +114,7 @@ ], ], 'OneTimePasswordAuthenticator' => [ - 'checker' => \CakeDC\Users\Auth\DefaultTwoFactorAuthenticationChecker::class, + 'checker' => \CakeDC\Auth\Authentication\DefaultTwoFactorAuthenticationChecker::class, 'verifyAction' => [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', From d574d45eff25c3dd2a73d1bb279792dcd32aaa8c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 20 Nov 2018 15:17:03 -0200 Subject: [PATCH 184/685] fixed flash message call --- src/Controller/Component/LoginComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index 8796c4a2d..90c85edb2 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -58,7 +58,7 @@ public function handleFailure($redirect = true) $service = $request->getAttribute('authentication'); $result = $this->getTargetAuthenticatorResult($service); - $controller->Flash->error($this->getErrorMessage($result), 'default', [], 'auth'); + $controller->Flash->error($this->getErrorMessage($result), ['element' => 'default', 'key' => 'auth']); if (!$redirect) { return null; From f3b66714299956b3a4ddc00106b1c2634e277b13 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 20 Nov 2018 15:21:03 -0200 Subject: [PATCH 185/685] fixed method call --- tests/TestCase/Authenticator/SocialAuthenticatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php index 047cc8fd5..548b82961 100644 --- a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php @@ -591,7 +591,7 @@ public function testAuthenticateErrorException($exception, $status) $service = (new ServiceFactory())->createFromProvider('facebook'); $this->Request = $this->Request->withAttribute('socialService', $service); - $identifiers = $this->getMockBuilder(IdentifierCollection::class, ['identify'])->getMock(); + $identifiers = $this->getMockBuilder(IdentifierCollection::class)->getMock(); $identifiers->expects($this->once()) ->method('identify') ->will($this->throwException($exception)); From 3418466404db40981e35dfe8c44dc9abf141e969 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 20 Nov 2018 15:39:22 -0200 Subject: [PATCH 186/685] moved one-time password component to auth plugin --- Docs/Documentation/Installation.md | 4 +- .../Documentation/Two-Factor-Authenticator.md | 2 +- composer.json | 5 +- config/routes.php | 2 +- config/users.php | 27 ++-- .../OneTimePasswordAuthenticatorComponent.php | 80 ----------- .../Traits/OneTimePasswordVerifyTrait.php | 2 +- src/Controller/UsersController.php | 6 +- src/Plugin.php | 4 +- src/Template/Users/edit.ctp | 2 +- ...TimePasswordAuthenticatorComponentTest.php | 126 ------------------ .../Traits/OneTimePasswordVerifyTraitTest.php | 12 +- tests/TestCase/PluginTest.php | 18 +-- 13 files changed, 40 insertions(+), 250 deletions(-) delete mode 100644 src/Controller/Component/OneTimePasswordAuthenticatorComponent.php delete mode 100644 tests/TestCase/Controller/Component/OneTimePasswordAuthenticatorComponentTest.php diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 0810d7792..d4c284d27 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -40,10 +40,10 @@ If you want to use Google Authenticator features... composer require robthree/twofactorauth:"^1.5.2" ``` -NOTE: you'll need to enable `Users.OneTimePasswordAuthenticator.login` +NOTE: you'll need to enable `OneTimePasswordAuthenticator.login` ``` -Configure::write('Users.OneTimePasswordAuthenticator.login', true); +Configure::write('OneTimePasswordAuthenticator.login', true); ``` Load the Plugin diff --git a/Docs/Documentation/Two-Factor-Authenticator.md b/Docs/Documentation/Two-Factor-Authenticator.md index 30464cdc1..0ee975fc8 100644 --- a/Docs/Documentation/Two-Factor-Authenticator.md +++ b/Docs/Documentation/Two-Factor-Authenticator.md @@ -16,7 +16,7 @@ Enable one-time password authenticator in your bootstrap.php file: Config/bootstrap.php ``` -Configure::write('Users.OneTimePasswordAuthenticator.login', true); +Configure::write('OneTimePasswordAuthenticator.login', true); ``` How does it work diff --git a/composer.json b/composer.json index 744fd1acd..744f92eef 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,7 @@ }, "require-dev": { "phpunit/phpunit": "^5.0", - "cakephp/cakephp-codesniffer": "^2.0", + "cakephp/cakephp-codesniffer": "^3.0", "league/oauth2-facebook": "@stable", "league/oauth2-instagram": "@stable", "league/oauth2-google": "@stable", @@ -43,8 +43,7 @@ "robthree/twofactorauth": "^1.6", "satooshi/php-coveralls": "^2.0", "league/oauth1-client": "^1.7", - "cakephp/authorization": "^1.0@beta", - "cakephp/cakephp-codesniffer": "^3.0" + "cakephp/authorization": "^1.0@beta" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", diff --git a/config/routes.php b/config/routes.php index 1261a2c61..8ddf940bd 100644 --- a/config/routes.php +++ b/config/routes.php @@ -22,7 +22,7 @@ 'action' => 'validate' ]); // Google Authenticator related routes -if (Configure::read('Users.OneTimePasswordAuthenticator.login')) { +if (Configure::read('OneTimePasswordAuthenticator.login')) { Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']); Router::connect('/resetOneTimePasswordAuthenticator', [ diff --git a/config/users.php b/config/users.php index 68708bea8..ae981dbf2 100644 --- a/config/users.php +++ b/config/users.php @@ -58,21 +58,6 @@ // enable social login 'login' => false, ], - 'OneTimePasswordAuthenticator' => [ - // 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, @@ -121,6 +106,18 @@ 'action' => 'verify', 'prefix' => false, ], + '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 ], 'Auth' => [ 'AuthenticationComponent' => [ diff --git a/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php b/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php deleted file mode 100644 index 75a8bc620..000000000 --- a/src/Controller/Component/OneTimePasswordAuthenticatorComponent.php +++ /dev/null @@ -1,80 +0,0 @@ -tfa = new TwoFactorAuth( - Configure::read('Users.OneTimePasswordAuthenticator.issuer'), - Configure::read('Users.OneTimePasswordAuthenticator.digits'), - Configure::read('Users.OneTimePasswordAuthenticator.period'), - Configure::read('Users.OneTimePasswordAuthenticator.algorithm'), - Configure::read('Users.OneTimePasswordAuthenticator.qrcodeprovider'), - Configure::read('Users.OneTimePasswordAuthenticator.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/Traits/OneTimePasswordVerifyTrait.php b/src/Controller/Traits/OneTimePasswordVerifyTrait.php index c32184779..2e5198603 100644 --- a/src/Controller/Traits/OneTimePasswordVerifyTrait.php +++ b/src/Controller/Traits/OneTimePasswordVerifyTrait.php @@ -57,7 +57,7 @@ public function verify() */ protected function isVerifyAllowed() { - if (!Configure::read('Users.OneTimePasswordAuthenticator.login')) { + if (!Configure::read('OneTimePasswordAuthenticator.login')) { $message = __d('CakeDC/Users', 'Please enable Google Authenticator first.'); $this->Flash->error($message, 'default', [], 'auth'); diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 6c1915718..5de5a6b5a 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -52,7 +52,7 @@ public function initialize() } /** - * Load all auth components needed: Authentication.Authentication, Authorization.Authorization and CakeDC/Users.OneTimePasswordAuthenticator + * Load all auth components needed: Authentication.Authentication, Authorization.Authorization and CakeDC/OneTimePasswordAuthenticator * * @return void */ @@ -69,8 +69,8 @@ protected function loadAuthComponents() $this->loadComponent('Authorization.Authorization', $config); } - if (Configure::read('Users.OneTimePasswordAuthenticator.login') !== false) { - $this->loadComponent('CakeDC/Users.OneTimePasswordAuthenticator'); + if (Configure::read('OneTimePasswordAuthenticator.login') !== false) { + $this->loadComponent('CakeDC/Auth.OneTimePasswordAuthenticator'); } } } diff --git a/src/Plugin.php b/src/Plugin.php index 7f0dd7e0d..97f1cd541 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -108,7 +108,7 @@ public function authentication() $service->loadAuthenticator($authenticator, $options); } - if (Configure::read('Users.OneTimePasswordAuthenticator.login')) { + if (Configure::read('OneTimePasswordAuthenticator.login')) { $service->loadAuthenticator('CakeDC/Auth.TwoFactor', [ 'skipGoogleVerify' => true, ]); @@ -131,7 +131,7 @@ public function middleware($middlewareQueue) $authentication = new AuthenticationMiddleware($this); $middlewareQueue->add($authentication); - if (Configure::read('Users.OneTimePasswordAuthenticator.login')) { + if (Configure::read('OneTimePasswordAuthenticator.login')) { $middlewareQueue->add(OneTimePasswordAuthenticatorMiddleware::class); } diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index 9a3772ba5..37bc19749 100644 --- a/src/Template/Users/edit.ctp +++ b/src/Template/Users/edit.ctp @@ -57,7 +57,7 @@ $Users = ${$tableAlias};
Form->button(__d('CakeDC/Users', 'Submit')) ?> Form->end() ?> - +
Reset Google Authenticator Form->postLink( diff --git a/tests/TestCase/Controller/Component/OneTimePasswordAuthenticatorComponentTest.php b/tests/TestCase/Controller/Component/OneTimePasswordAuthenticatorComponentTest.php deleted file mode 100644 index 39c1a38c4..000000000 --- a/tests/TestCase/Controller/Component/OneTimePasswordAuthenticatorComponentTest.php +++ /dev/null @@ -1,126 +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.OneTimePasswordAuthenticator.login', true); - - $this->request = $this->getMockBuilder('Cake\Http\ServerRequest') - ->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->OneTimePasswordAuthenticator = new OneTimePasswordAuthenticatorComponent($this->Registry); - } - - /** - * tearDown method - * - * @return void - */ - public function tearDown() - { - parent::tearDown(); - - $_SESSION = []; - unset($this->Controller, $this->OneTimePasswordAuthenticator); - Configure::write('Users', $this->backupUsersConfig); - Configure::write('Users.OneTimePasswordAuthenticator.login', false); - } - - /** - * Test initialize - * - */ - public function testInitialize() - { - $this->Controller->OneTimePasswordAuthenticator = new OneTimePasswordAuthenticatorComponent($this->Registry); - $this->assertInstanceOf('CakeDC\Users\Controller\Component\OneTimePasswordAuthenticatorComponent', $this->Controller->OneTimePasswordAuthenticator); - } - - /** - * test base64 qr-code returned from component - * @return void - */ - public function testgetQRCodeImageAsDataUri() - { - $this->Controller->OneTimePasswordAuthenticator->initialize([]); - $result = $this->Controller->OneTimePasswordAuthenticator->getQRCodeImageAsDataUri('test@localhost.com', '123123'); - - $this->assertContains('data:image/png;base64', $result); - } - - /** - * Making sure we return secret - * @return void - */ - public function testCreateSecret() - { - $this->Controller->OneTimePasswordAuthenticator->initialize([]); - $result = $this->Controller->OneTimePasswordAuthenticator->createSecret(); - $this->assertNotEmpty($result); - } - - /** - * Testing code verification in the component - * @return void - */ - public function testVerifyCode() - { - $this->Controller->OneTimePasswordAuthenticator->initialize([]); - $secret = $this->Controller->OneTimePasswordAuthenticator->createSecret(); - $verificationCode = $this->Controller->OneTimePasswordAuthenticator->tfa->getCode($secret); - - $verified = $this->Controller->OneTimePasswordAuthenticator->verifyCode($secret, $verificationCode); - $this->assertTrue($verified); - } -} diff --git a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php index 86deea91c..1cbac9bc8 100644 --- a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php +++ b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php @@ -11,7 +11,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits; -use CakeDC\Users\Controller\Component\OneTimePasswordAuthenticatorComponent; +use CakeDC\Auth\Controller\Component\OneTimePasswordAuthenticatorComponent; use Cake\Core\Configure; use Cake\Http\ServerRequest; use Cake\ORM\TableRegistry; @@ -61,7 +61,7 @@ public function tearDown() */ public function testVerifyHappy() { - Configure::write('Users.OneTimePasswordAuthenticator.login', true); + Configure::write('OneTimePasswordAuthenticator.login', true); $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') ->setMethods(['is', 'getData', 'allow', 'getSession']) ->getMock(); @@ -89,7 +89,7 @@ public function testVerifyHappy() public function testVerifyNotEnabled() { $this->_mockFlash(); - Configure::write('Users.OneTimePasswordAuthenticator.login', false); + Configure::write('OneTimePasswordAuthenticator.login', false); $this->Trait->request = $this->Trait->request->withQueryParams(['redirect' => 'dashboard/list']); $this->Trait->Flash->expects($this->once()) ->method('error') @@ -107,7 +107,7 @@ public function testVerifyNotEnabled() */ public function testVerifyGetShowQR() { - Configure::write('Users.OneTimePasswordAuthenticator.login', true); + Configure::write('OneTimePasswordAuthenticator.login', true); $this->Trait->OneTimePasswordAuthenticator = $this->getMockBuilder(OneTimePasswordAuthenticatorComponent::class) ->disableOriginalConstructor() ->setMethods(['createSecret', 'getQRCodeImageAsDataUri']) @@ -153,7 +153,7 @@ public function testVerifyGetShowQR() */ public function testVerifyGetGeneratesNewSecret() { - Configure::write('Users.OneTimePasswordAuthenticator.login', true); + Configure::write('OneTimePasswordAuthenticator.login', true); $this->Trait->OneTimePasswordAuthenticator = $this ->getMockBuilder(OneTimePasswordAuthenticatorComponent::class) @@ -212,7 +212,7 @@ public function testVerifyGetGeneratesNewSecret() */ public function testVerifyGetDoesNotGenerateNewSecret() { - Configure::write('Users.OneTimePasswordAuthenticator.login', true); + Configure::write('OneTimePasswordAuthenticator.login', true); $this->Trait->OneTimePasswordAuthenticator = $this ->getMockBuilder(OneTimePasswordAuthenticatorComponent::class) diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index f5989ffd1..63f87ecbc 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -41,7 +41,7 @@ class PluginTest extends IntegrationTestCase public function testMiddleware() { Configure::write('Users.Social.login', true); - Configure::write('Users.OneTimePasswordAuthenticator.login', true); + Configure::write('OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); Configure::write('Auth.Authorization.loadRbacMiddleware', false); @@ -68,7 +68,7 @@ public function testMiddleware() public function testMiddlewareAuthorizationMiddlewareAndRbacMiddleware() { Configure::write('Users.Social.login', true); - Configure::write('Users.OneTimePasswordAuthenticator.login', true); + Configure::write('OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); Configure::write('Auth.Authorization.loadRbacMiddleware', true); @@ -96,7 +96,7 @@ public function testMiddlewareAuthorizationMiddlewareAndRbacMiddleware() public function testMiddlewareAuthorizationOnlyRbacMiddleware() { Configure::write('Users.Social.login', true); - Configure::write('Users.OneTimePasswordAuthenticator.login', true); + Configure::write('OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', false); Configure::write('Auth.Authorization.loadRbacMiddleware', true); @@ -122,7 +122,7 @@ public function testMiddlewareAuthorizationOnlyRbacMiddleware() public function testMiddlewareWithoutAuhorization() { Configure::write('Users.Social.login', true); - Configure::write('Users.OneTimePasswordAuthenticator.login', true); + Configure::write('OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', false); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true);//ignore Configure::write('Auth.Authorization.loadRbacMiddleware', true);//ignore @@ -147,7 +147,7 @@ public function testMiddlewareWithoutAuhorization() public function testMiddlewareNotSocial() { Configure::write('Users.Social.login', false); - Configure::write('Users.OneTimePasswordAuthenticator.login', true); + Configure::write('OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); Configure::write('Auth.Authorization.loadRbacMiddleware', false); @@ -170,7 +170,7 @@ public function testMiddlewareNotSocial() public function testMiddlewareNotOneTimePasswordAuthenticator() { Configure::write('Users.Social.login', true); - Configure::write('Users.OneTimePasswordAuthenticator.login', false); + Configure::write('OneTimePasswordAuthenticator.login', false); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); Configure::write('Auth.Authorization.loadRbacMiddleware', false); @@ -194,7 +194,7 @@ public function testMiddlewareNotOneTimePasswordAuthenticator() public function testMiddlewareNotGoogleAuthenticationAndNotSocial() { Configure::write('Users.Social.login', false); - Configure::write('Users.OneTimePasswordAuthenticator.login', false); + Configure::write('OneTimePasswordAuthenticator.login', false); Configure::write('Auth.Authorization.enable', true); Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); Configure::write('Auth.Authorization.loadRbacMiddleware', false); @@ -271,7 +271,7 @@ public function testGetAuthenticationService() ], 'Authentication.JwtSubject' ]); - Configure::write('Users.OneTimePasswordAuthenticator.login', true); + Configure::write('OneTimePasswordAuthenticator.login', true); $plugin = new Plugin(); $service = $plugin->getAuthenticationService(new ServerRequest(), new Response()); @@ -375,7 +375,7 @@ public function testGetAuthenticationServiceWithouOneTimePasswordAuthenticator() ], 'Authentication.JwtSubject' ]); - Configure::write('Users.OneTimePasswordAuthenticator.login', false); + Configure::write('OneTimePasswordAuthenticator.login', false); $plugin = new Plugin(); $service = $plugin->getAuthenticationService(new ServerRequest(), new Response()); From 0a308f8a58e8430719d2af3620893fe66d570824 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 20 Nov 2018 16:12:11 -0200 Subject: [PATCH 187/685] compatibility with php 5.6 --- src/Controller/Traits/LinkSocialTrait.php | 4 +++- src/Controller/Traits/LoginTrait.php | 3 ++- src/Controller/Traits/PasswordManagementTrait.php | 6 ++++-- src/Controller/Traits/ProfileTrait.php | 4 +++- src/Controller/Traits/RegisterTrait.php | 4 +++- tests/Fixture/UsersFixture.php | 2 -- 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index afa6194df..063f9fc89 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -62,7 +62,9 @@ public function callbackLinkSocial($alias = null) } $data = $server->getUser($this->request); $data = (new MapUser())($server, $data); - $userId = Hash::get($this->request->getAttribute('identity') ?? [], 'id'); + $identity = $this->request->getAttribute('identity'); + $identity = isset($identity) ? $identity : []; + $userId = Hash::get($identity, 'id'); $user = $this->getUsersTable()->get($userId); $this->getUsersTable()->linkSocialAccount($user, $data); diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 0df018e6f..2eb2e07c6 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -67,7 +67,8 @@ public function login() */ public function logout() { - $user = $this->request->getAttribute('identity') ?? []; + $user = $this->request->getAttribute('identity'); + $user = isset($user) ? $user : []; $eventBefore = $this->dispatchEvent(Plugin::EVENT_BEFORE_LOGOUT, ['user' => $user]); if (is_array($eventBefore->result)) { diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 79a5ab3cd..01d2fec68 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -37,10 +37,12 @@ trait PasswordManagementTrait public function changePassword() { $user = $this->getUsersTable()->newEntity(); - $id = Hash::get($this->request->getAttribute('identity') ?? [], 'id'); + $identity = $this->request->getAttribute('identity'); + $identity = isset($identity) ? $identity : []; + $id = Hash::get($identity, 'id'); if (!empty($id)) { - $user->id = Hash::get($this->request->getAttribute('identity') ?? [], 'id'); + $user->id = $id; $validatePassword = true; //@todo add to the documentation: list of routes used $redirect = Configure::read('Users.Profile.route'); diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index 15a01a0c2..f399e5540 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -32,7 +32,9 @@ trait ProfileTrait */ public function profile($id = null) { - $loggedUserId = Hash::get($this->request->getAttribute('identity') ?? [], 'id'); + $identity = $this->request->getAttribute('identity'); + $identity = isset($identity) ? $identity : []; + $loggedUserId = Hash::get($identity, 'id'); $isCurrentUser = false; if (!Configure::read('Users.Profile.viewOthers') || empty($id)) { $id = $loggedUserId; diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 1d41972ba..5992906c0 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -39,7 +39,9 @@ public function register() throw new NotFoundException(); } - $userId = Hash::get($this->request->getAttribute('identity') ?? [], 'id'); + $identity = $this->request->getAttribute('identity'); + $identity = isset($identity) ? $identity : []; + $userId = Hash::get($identity, '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')); diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index d0256aed8..f6a38a98c 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -117,7 +117,6 @@ class UsersFixture extends TestFixture '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' @@ -138,7 +137,6 @@ class UsersFixture extends TestFixture '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' From abd36529cd8c4eec24e1e10bd2db453fc00b0ec5 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 20 Nov 2018 16:27:22 -0200 Subject: [PATCH 188/685] making sure files has copyright --- config/Migrations/20150513201111_initial.php | 4 ++-- config/Migrations/20161031101316_AddSecretToUsers.php | 4 ++-- config/bootstrap.php | 4 ++-- config/permissions.php | 4 ++-- config/routes.php | 4 ++-- config/users.php | 4 ++-- phpunit.xml.dist | 10 ++++++++++ src/Controller/AppController.php | 4 ++-- src/Controller/Component/LoginComponent.php | 10 ++++++++++ src/Controller/Component/SetupComponent.php | 2 +- src/Controller/SocialAccountsController.php | 4 ++-- src/Controller/Traits/CustomUsersTableTrait.php | 4 ++-- src/Controller/Traits/LinkSocialTrait.php | 4 ++-- src/Controller/Traits/LoginTrait.php | 4 ++-- src/Controller/Traits/OneTimePasswordVerifyTrait.php | 9 +++++++++ src/Controller/Traits/PasswordManagementTrait.php | 4 ++-- src/Controller/Traits/ProfileTrait.php | 4 ++-- src/Controller/Traits/ReCaptchaTrait.php | 4 ++-- src/Controller/Traits/RegisterTrait.php | 4 ++-- src/Controller/Traits/SimpleCrudTrait.php | 4 ++-- src/Controller/Traits/SocialTrait.php | 4 ++-- src/Controller/Traits/UserValidationTrait.php | 4 ++-- src/Controller/UsersController.php | 4 ++-- src/Exception/AccountAlreadyActiveException.php | 4 ++-- src/Exception/AccountNotActiveException.php | 4 ++-- src/Exception/MissingEmailException.php | 4 ++-- src/Exception/TokenExpiredException.php | 4 ++-- src/Exception/UserAlreadyActiveException.php | 4 ++-- src/Exception/UserNotActiveException.php | 4 ++-- src/Exception/UserNotFoundException.php | 4 ++-- src/Exception/WrongPasswordException.php | 4 ++-- src/Mailer/UsersMailer.php | 4 ++-- src/Middleware/SocialAuthMiddleware.php | 9 +++++++++ src/Middleware/SocialEmailMiddleware.php | 9 +++++++++ src/Model/Behavior/AuthFinderBehavior.php | 4 ++-- src/Model/Behavior/BaseTokenBehavior.php | 4 ++-- src/Model/Behavior/LinkSocialBehavior.php | 4 ++-- src/Model/Behavior/PasswordBehavior.php | 4 ++-- src/Model/Behavior/RegisterBehavior.php | 4 ++-- src/Model/Behavior/SocialAccountBehavior.php | 4 ++-- src/Model/Behavior/SocialBehavior.php | 4 ++-- src/Model/Entity/SocialAccount.php | 4 ++-- src/Model/Entity/User.php | 4 ++-- src/Model/Table/SocialAccountsTable.php | 4 ++-- src/Model/Table/UsersTable.php | 4 ++-- src/Plugin.php | 10 ++++++++++ src/Shell/UsersShell.php | 4 ++-- src/Template/Email/html/reset_password.ctp | 4 ++-- src/Template/Email/html/social_account_validation.ctp | 4 ++-- src/Template/Email/html/validation.ctp | 4 ++-- src/Template/Email/text/reset_password.ctp | 4 ++-- src/Template/Email/text/social_account_validation.ctp | 4 ++-- src/Template/Email/text/validation.ctp | 4 ++-- src/Template/Layout/Email/html/default.ctp | 4 ++-- src/Template/Layout/Email/text/default.ctp | 4 ++-- src/Template/Users/add.ctp | 4 ++-- src/Template/Users/edit.ctp | 4 ++-- src/Template/Users/index.ctp | 4 ++-- src/Template/Users/login.ctp | 4 ++-- src/Template/Users/profile.ctp | 4 ++-- src/Template/Users/register.ctp | 4 ++-- src/Template/Users/resend_token_validation.ctp | 4 ++-- src/Template/Users/social_email.ctp | 4 ++-- src/Template/Users/view.ctp | 4 ++-- src/Traits/RandomStringTrait.php | 4 ++-- src/View/Helper/UserHelper.php | 4 ++-- tests/App/Controller/AppController.php | 4 ++-- tests/App/Mailer/OverrideMailer.php | 4 ++-- tests/App/Template/Layout/Email/html/default.ctp | 10 ++++++++++ tests/App/Template/Layout/Email/text/default.ctp | 10 ++++++++++ tests/Fixture/PostsFixture.php | 4 ++-- tests/Fixture/PostsUsersFixture.php | 4 ++-- tests/Fixture/SocialAccountsFixture.php | 4 ++-- tests/Fixture/UsersFixture.php | 4 ++-- .../Controller/SocialAccountsControllerTest.php | 4 ++-- tests/TestCase/Controller/Traits/BaseTraitTest.php | 4 ++-- .../Controller/Traits/CustomUsersTableTraitTest.php | 4 ++-- .../Controller/Traits/LinkSocialTraitTest.php | 4 ++-- tests/TestCase/Controller/Traits/LoginTraitTest.php | 4 ++-- .../Traits/OneTimePasswordVerifyTraitTest.php | 4 ++-- .../Controller/Traits/PasswordManagementTraitTest.php | 4 ++-- tests/TestCase/Controller/Traits/ProfileTraitTest.php | 4 ++-- .../TestCase/Controller/Traits/RecaptchaTraitTest.php | 4 ++-- .../TestCase/Controller/Traits/RegisterTraitTest.php | 4 ++-- .../Controller/Traits/SimpleCrudTraitTest.php | 4 ++-- tests/TestCase/Controller/Traits/SocialTraitTest.php | 4 ++-- .../Controller/Traits/UserValidationTraitTest.php | 4 ++-- .../Exception/AccountAlreadyActiveExceptionTest.php | 4 ++-- .../Exception/AccountNotActiveExceptionTest.php | 4 ++-- .../TestCase/Exception/MissingEmailExceptionTest.php | 4 ++-- .../TestCase/Exception/TokenExpiredExceptionTest.php | 4 ++-- .../Exception/UserAlreadyActiveExceptionTest.php | 4 ++-- .../TestCase/Exception/UserNotActiveExceptionTest.php | 4 ++-- .../TestCase/Exception/UserNotFoundExceptionTest.php | 4 ++-- .../TestCase/Exception/WrongPasswordExceptionTest.php | 4 ++-- tests/TestCase/Mailer/UsersMailerTest.php | 4 ++-- .../TestCase/Middleware/SocialAuthMiddlewareTest.php | 11 +++++++---- .../TestCase/Middleware/SocialEmailMiddlewareTest.php | 9 +++++++++ .../Model/Behavior/AuthFinderBehaviorTest.php | 4 ++-- .../Model/Behavior/LinkSocialBehaviorTest.php | 4 ++-- .../TestCase/Model/Behavior/PasswordBehaviorTest.php | 4 ++-- .../TestCase/Model/Behavior/RegisterBehaviorTest.php | 4 ++-- .../Model/Behavior/SocialAccountBehaviorTest.php | 4 ++-- tests/TestCase/Model/Behavior/SocialBehaviorTest.php | 4 ++-- tests/TestCase/Model/Entity/UserTest.php | 4 ++-- .../TestCase/Model/Table/SocialAccountsTableTest.php | 4 ++-- tests/TestCase/Model/Table/UsersTableTest.php | 4 ++-- tests/TestCase/PluginTest.php | 9 +++++++++ tests/TestCase/Shell/UsersShellTest.php | 4 ++-- tests/TestCase/Traits/RandomStringTraitTest.php | 4 ++-- tests/TestCase/View/Helper/AuthLinkHelperTest.php | 4 ++-- tests/TestCase/View/Helper/UserHelperTest.php | 4 ++-- tests/bootstrap.php | 4 ++-- tests/config/routes.php | 4 ++-- 114 files changed, 307 insertions(+), 209 deletions(-) diff --git a/config/Migrations/20150513201111_initial.php b/config/Migrations/20150513201111_initial.php index 55b00f094..872de2eee 100644 --- a/config/Migrations/20150513201111_initial.php +++ b/config/Migrations/20150513201111_initial.php @@ -1,11 +1,11 @@ + + diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp index 8a1840468..366453c4a 100644 --- a/src/Template/Email/html/validation.ctp +++ b/src/Template/Email/html/validation.ctp @@ -1,11 +1,11 @@ diff --git a/src/Template/Layout/Email/text/default.ctp b/src/Template/Layout/Email/text/default.ctp index 686aa84ab..2695bc38c 100644 --- a/src/Template/Layout/Email/text/default.ctp +++ b/src/Template/Layout/Email/text/default.ctp @@ -1,11 +1,11 @@ diff --git a/src/Template/Users/add.ctp b/src/Template/Users/add.ctp index 751b2f3c6..37115c609 100644 --- a/src/Template/Users/add.ctp +++ b/src/Template/Users/add.ctp @@ -1,11 +1,11 @@ diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index 37bc19749..cf0f0504b 100644 --- a/src/Template/Users/edit.ctp +++ b/src/Template/Users/edit.ctp @@ -1,11 +1,11 @@ diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index 5e08f7cd6..a1b0b0b5e 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -1,11 +1,11 @@ diff --git a/src/Template/Users/register.ctp b/src/Template/Users/register.ctp index 3fe773fee..59502d11b 100644 --- a/src/Template/Users/register.ctp +++ b/src/Template/Users/register.ctp @@ -1,11 +1,11 @@ diff --git a/src/Template/Users/social_email.ctp b/src/Template/Users/social_email.ctp index b0a272b6d..05f1c2f80 100644 --- a/src/Template/Users/social_email.ctp +++ b/src/Template/Users/social_email.ctp @@ -1,11 +1,11 @@ diff --git a/src/Template/Users/view.ctp b/src/Template/Users/view.ctp index d2e21bf7a..e52b6376a 100644 --- a/src/Template/Users/view.ctp +++ b/src/Template/Users/view.ctp @@ -1,11 +1,11 @@ fetch('content'); diff --git a/tests/App/Template/Layout/Email/text/default.ctp b/tests/App/Template/Layout/Email/text/default.ctp index 21c7e0044..27c784592 100644 --- a/tests/App/Template/Layout/Email/text/default.ctp +++ b/tests/App/Template/Layout/Email/text/default.ctp @@ -1,2 +1,12 @@ fetch('content'); diff --git a/tests/Fixture/PostsFixture.php b/tests/Fixture/PostsFixture.php index 257e98be2..6034d6dd4 100644 --- a/tests/Fixture/PostsFixture.php +++ b/tests/Fixture/PostsFixture.php @@ -1,11 +1,11 @@ Date: Tue, 20 Nov 2018 16:39:24 -0200 Subject: [PATCH 189/685] updated cakephp/authentication and cakephp/authorization --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 744f92eef..f4e28d869 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,8 @@ "require": { "cakephp/cakephp": "^3.6", "cakedc/auth": "^3.0", - "cakephp/authentication": "^1.0@RC" + "cakephp/authentication": "^1.0", + "cakephp/authorization": "^1.0" }, "require-dev": { "phpunit/phpunit": "^5.0", @@ -42,8 +43,7 @@ "google/recaptcha": "@stable", "robthree/twofactorauth": "^1.6", "satooshi/php-coveralls": "^2.0", - "league/oauth1-client": "^1.7", - "cakephp/authorization": "^1.0@beta" + "league/oauth1-client": "^1.7" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", From 6ed672ce50f31e6462573b17096f054a2bbd3db8 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 16:27:31 -0200 Subject: [PATCH 190/685] Added authorization service loader --- config/users.php | 1 + src/Loader/AuthorizationServiceLoader.php | 44 +++++++++++++++++++++++ src/Plugin.php | 18 +++------- tests/TestCase/PluginTest.php | 2 +- 4 files changed, 50 insertions(+), 15 deletions(-) create mode 100644 src/Loader/AuthorizationServiceLoader.php diff --git a/config/users.php b/config/users.php index d960e9819..dd2e33e80 100644 --- a/config/users.php +++ b/config/users.php @@ -192,6 +192,7 @@ 'enable' => true, 'loadAuthorizationMiddleware' => true, 'loadRbacMiddleware' => false, + 'serviceLoader' => \CakeDC\Users\Loader\AuthorizationServiceLoader::class ], 'AuthorizationMiddleware' => [ 'unauthorizedHandler' => [ diff --git a/src/Loader/AuthorizationServiceLoader.php b/src/Loader/AuthorizationServiceLoader.php new file mode 100644 index 000000000..39887880d --- /dev/null +++ b/src/Loader/AuthorizationServiceLoader.php @@ -0,0 +1,44 @@ +map(ServerRequest::class, RbacPolicy::class); + + $orm = new OrmResolver(); + + $resolver = new ResolverCollection([ + $map, + $orm + ]); + + return new AuthorizationService($resolver); + } +} \ No newline at end of file diff --git a/src/Plugin.php b/src/Plugin.php index adae3c5ea..c7840b0b0 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -71,22 +71,12 @@ public function getAuthenticationService(ServerRequestInterface $request, Respon */ public function getAuthorizationService(ServerRequestInterface $request, ResponseInterface $response) { - $serviceLoader = Configure::read('Auth.Authorization.service'); - if ($serviceLoader !== null) { - return $serviceLoader($request, $response); + $serviceLoader = Configure::read('Auth.Authorization.serviceLoader'); + if (is_string($serviceLoader)) { + $serviceLoader = new $serviceLoader(); } - $map = new MapResolver(); - $map->map(ServerRequest::class, RbacPolicy::class); - - $orm = new OrmResolver(); - - $resolver = new ResolverCollection([ - $map, - $orm - ]); - - return new AuthorizationService($resolver); + return $serviceLoader($request, $response); } /** diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 7086e09cd..923aea14b 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -444,7 +444,7 @@ public function testGetAuthorizationServiceCallableDefined() $request->withQueryParams(['method' => __METHOD__]); $response = new Response(['body' => __METHOD__]); $service = new AuthorizationService(new ResolverCollection()); - Configure::write('Auth.Authorization.service', function ($aRequest, $aResponse) use ($request, $response, $service) { + Configure::write('Auth.Authorization.serviceLoader', function ($aRequest, $aResponse) use ($request, $response, $service) { $this->assertSame($request, $aRequest); $this->assertSame($response, $aResponse); From 2462a273d4f96519f6af15592f6f2e7e7fb022c4 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 16:52:11 -0200 Subject: [PATCH 191/685] Added authentication service loader --- config/users.php | 3 + src/Loader/AuthenticationServiceLoader.php | 96 ++++++++++++++++++++++ src/Plugin.php | 73 ++++++---------- tests/TestCase/PluginTest.php | 2 +- 4 files changed, 123 insertions(+), 51 deletions(-) create mode 100644 src/Loader/AuthenticationServiceLoader.php diff --git a/config/users.php b/config/users.php index dd2e33e80..d0daa2987 100644 --- a/config/users.php +++ b/config/users.php @@ -120,6 +120,9 @@ 'rngprovider' => null ], 'Auth' => [ + 'Authentication' => [ + 'serviceLoader' => \CakeDC\Users\Loader\AuthenticationServiceLoader::class + ], 'AuthenticationComponent' => [ 'load' => true, 'loginAction' => [ diff --git a/src/Loader/AuthenticationServiceLoader.php b/src/Loader/AuthenticationServiceLoader.php new file mode 100644 index 000000000..7eb819606 --- /dev/null +++ b/src/Loader/AuthenticationServiceLoader.php @@ -0,0 +1,96 @@ +loadIdentifiers($service); + $this->loadAuthenticators($service); + $this->loadTwoFactorAuthenticator($service); + + return $service; + } + + /** + * Load the indentifiers defined at config Auth.Identifiers + * + * @param \CakeDC\Auth\Authentication\AuthenticationService $service Authentication service to load identifiers + * @return void + */ + protected function loadIdentifiers($service) + { + $identifiers = Configure::read('Auth.Identifiers'); + foreach ($identifiers as $identifier => $options) { + if (is_numeric($identifier)) { + $identifier = $options; + $options = []; + } + + $service->loadIdentifier($identifier, $options); + } + } + + /** + * Load the authenticators defined at config Auth.Authenticators + * + * @param \CakeDC\Auth\Authentication\AuthenticationService $service Authentication service to load identifiers + * + * @return void + */ + protected function loadAuthenticators($service) + { + $authenticators = Configure::read('Auth.Authenticators'); + foreach ($authenticators as $authenticator => $options) { + if (is_numeric($authenticator)) { + $authenticator = $options; + $options = []; + } + + $service->loadAuthenticator($authenticator, $options); + } + } + + /** + * Load the CakeDC/Auth.TwoFactor based on config OneTimePasswordAuthenticator.login + * + * @param \CakeDC\Auth\Authentication\AuthenticationService $service Authentication service to load identifiers + * + * @return void + */ + protected function loadTwoFactorAuthenticator($service) + { + if (Configure::read('OneTimePasswordAuthenticator.login') !== false) { + $service->loadAuthenticator('CakeDC/Auth.TwoFactor', [ + 'skipGoogleVerify' => true, + ]); + } + } +} \ No newline at end of file diff --git a/src/Plugin.php b/src/Plugin.php index c7840b0b0..7b3aaa604 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -58,12 +58,8 @@ class Plugin extends BasePlugin implements AuthenticationServiceProviderInterfac */ public function getAuthenticationService(ServerRequestInterface $request, ResponseInterface $response) { - $serviceLoader = Configure::read('Auth.Authentication.service'); - if ($serviceLoader !== null) { - return $serviceLoader($request, $response); - } - - return $this->authentication(); + $key = 'Auth.Authentication.serviceLoader'; + return $this->loadService($request, $response, $key); } /** @@ -71,50 +67,8 @@ public function getAuthenticationService(ServerRequestInterface $request, Respon */ public function getAuthorizationService(ServerRequestInterface $request, ResponseInterface $response) { - $serviceLoader = Configure::read('Auth.Authorization.serviceLoader'); - if (is_string($serviceLoader)) { - $serviceLoader = new $serviceLoader(); - } - - return $serviceLoader($request, $response); - } - - /** - * load authenticators and identifiers - * - * @return AuthenticationServiceInterface - */ - public function authentication() - { - $service = new AuthenticationService(); - $authenticators = Configure::read('Auth.Authenticators'); - $identifiers = Configure::read('Auth.Identifiers'); - - foreach ($identifiers as $identifier => $options) { - if (is_numeric($identifier)) { - $identifier = $options; - $options = []; - } - - $service->loadIdentifier($identifier, $options); - } - - foreach ($authenticators as $authenticator => $options) { - if (is_numeric($authenticator)) { - $authenticator = $options; - $options = []; - } - - $service->loadAuthenticator($authenticator, $options); - } - - if (Configure::read('OneTimePasswordAuthenticator.login')) { - $service->loadAuthenticator('CakeDC/Auth.TwoFactor', [ - 'skipGoogleVerify' => true, - ]); - } - - return $service; + $key = 'Auth.Authorization.serviceLoader'; + return $this->loadService($request, $response, $key); } /** @@ -163,4 +117,23 @@ protected function addAuthorizationMiddleware(MiddlewareQueue $middlewareQueue) return $middlewareQueue; } + + /** + * Load a service defined in configuration $loaderKey + * + * @param ServerRequestInterface $request The request. + * @param ResponseInterface $response The response. + * @param string $loaderKey service loader key + * + * @return mixed + */ + protected function loadService(ServerRequestInterface $request, ResponseInterface $response, $loaderKey) + { + $serviceLoader = Configure::read($loaderKey); + if (is_string($serviceLoader)) { + $serviceLoader = new $serviceLoader(); + } + + return $serviceLoader($request, $response); + } } diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 923aea14b..753eae330 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -232,7 +232,7 @@ public function testGetAuthenticationServiceCallableDefined() 'Authentication.Password' ] ]); - Configure::write('Auth.Authentication.service', function ($aRequest, $aResponse) use ($request, $response, $service) { + Configure::write('Auth.Authentication.serviceLoader', function ($aRequest, $aResponse) use ($request, $response, $service) { $this->assertSame($request, $aRequest); $this->assertSame($response, $aResponse); From f4f10c7e7ce7cf864da8fd2f369027c4ee223bc5 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 17:19:28 -0200 Subject: [PATCH 192/685] Added middleware queue loader --- config/users.php | 1 + src/Loader/MiddlewareQueueLoader.php | 124 +++++++++++++++++++++++++++ src/Plugin.php | 56 ++++-------- 3 files changed, 141 insertions(+), 40 deletions(-) create mode 100644 src/Loader/MiddlewareQueueLoader.php diff --git a/config/users.php b/config/users.php index d0daa2987..a57bb0cc1 100644 --- a/config/users.php +++ b/config/users.php @@ -20,6 +20,7 @@ 'controller' => 'CakeDC/Users.Users', // Password Hasher 'passwordHasher' => '\Cake\Auth\DefaultPasswordHasher', + 'middlewareQueueLoader' => \CakeDC\Users\Loader\MiddlewareQueueLoader::class, // token expiration, 1 hour 'Token' => ['expiration' => 3600], 'Email' => [ diff --git a/src/Loader/MiddlewareQueueLoader.php b/src/Loader/MiddlewareQueueLoader.php new file mode 100644 index 000000000..6e2479e0c --- /dev/null +++ b/src/Loader/MiddlewareQueueLoader.php @@ -0,0 +1,124 @@ +loadSocialMiddleware($middlewareQueue); + $this->loadAuthenticationMiddleware($middlewareQueue, $plugin); + $this->load2faMiddleware($middlewareQueue); + + return $this->loadAuthorizationMiddleware($middlewareQueue, $plugin); + } + + /** + * Load social middlewares if enabled. Based on config 'Users.Social.login' + * + * @param MiddlewareQueue $middlewareQueue + * + * @return void + */ + protected function loadSocialMiddleware(MiddlewareQueue $middlewareQueue) + { + if (Configure::read('Users.Social.login')) { + $middlewareQueue + ->add(SocialAuthMiddleware::class) + ->add(SocialEmailMiddleware::class); + } + } + + /** + * Load authentication middleware + * + * @param \Cake\Http\MiddlewareQueue $middlewareQueue queue of middleware + * @param \CakeDC\Users\Plugin $plugin Users plugin object + * + * @return void + */ + protected function loadAuthenticationMiddleware(MiddlewareQueue $middlewareQueue, Plugin $plugin) + { + $authentication = new AuthenticationMiddleware($plugin); + $middlewareQueue->add($authentication); + } + + /** + * Load OneTimePasswordAuthenticatorMiddleware if enabled. Based on config 'OneTimePasswordAuthenticator.login' + * + * @param \Cake\Http\MiddlewareQueue $middlewareQueue queue of middleware + * + * @return void + */ + protected function load2faMiddleware(MiddlewareQueue $middlewareQueue) + { + if (Configure::read('OneTimePasswordAuthenticator.login')) { + $middlewareQueue->add(OneTimePasswordAuthenticatorMiddleware::class); + } + } + + /** + * Load authorization middleware based on Auth.Authorization. + * + * @param \Cake\Http\MiddlewareQueue $middlewareQueue queue of middleware + * @param \CakeDC\Users\Plugin $plugin Users plugin object + * + * @return \Cake\Http\MiddlewareQueue + */ + protected function loadAuthorizationMiddleware(MiddlewareQueue $middlewareQueue, Plugin $plugin) + { + if (Configure::read('Auth.Authorization.enable') === false) { + return $middlewareQueue; + } + + if (Configure::read('Auth.Authorization.loadAuthorizationMiddleware') !== false) { + $middlewareQueue->add(new AuthorizationMiddleware($plugin, Configure::read('Auth.AuthorizationMiddleware'))); + $middlewareQueue->add(new RequestAuthorizationMiddleware()); + } + + if (Configure::read('Auth.Authorization.loadRbacMiddleware') !== false) { + $middlewareQueue->add(new RbacMiddleware(null, Configure::read('Auth.RbacMiddleware'))); + } + + return $middlewareQueue; + } +} \ No newline at end of file diff --git a/src/Plugin.php b/src/Plugin.php index 7b3aaa604..0213bc534 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -76,46 +76,9 @@ public function getAuthorizationService(ServerRequestInterface $request, Respons */ public function middleware($middlewareQueue) { - if (Configure::read('Users.Social.login')) { - $middlewareQueue - ->add(SocialAuthMiddleware::class) - ->add(SocialEmailMiddleware::class); - } - - $authentication = new AuthenticationMiddleware($this); - $middlewareQueue->add($authentication); - - if (Configure::read('OneTimePasswordAuthenticator.login')) { - $middlewareQueue->add(OneTimePasswordAuthenticatorMiddleware::class); - } - - $middlewareQueue = $this->addAuthorizationMiddleware($middlewareQueue); - - return $middlewareQueue; - } - - /** - * Add authorization middleware based on Auth.Authorization - * - * @param MiddlewareQueue $middlewareQueue queue of middleware - * @return MiddlewareQueue - */ - protected function addAuthorizationMiddleware(MiddlewareQueue $middlewareQueue) - { - if (Configure::read('Auth.Authorization.enable') === false) { - return $middlewareQueue; - } + $loader = $this->getLoader('Users.middlewareQueueLoader'); - if (Configure::read('Auth.Authorization.loadAuthorizationMiddleware') !== false) { - $middlewareQueue->add(new AuthorizationMiddleware($this, Configure::read('Auth.AuthorizationMiddleware'))); - $middlewareQueue->add(new RequestAuthorizationMiddleware()); - } - - if (Configure::read('Auth.Authorization.loadRbacMiddleware') !== false) { - $middlewareQueue->add(new RbacMiddleware(null, Configure::read('Auth.RbacMiddleware'))); - } - - return $middlewareQueue; + return $loader($middlewareQueue, $this); } /** @@ -128,12 +91,25 @@ protected function addAuthorizationMiddleware(MiddlewareQueue $middlewareQueue) * @return mixed */ protected function loadService(ServerRequestInterface $request, ResponseInterface $response, $loaderKey) + { + $serviceLoader = $this->getLoader($loaderKey); + + return $serviceLoader($request, $response); + } + + /** + * Get the loader callable + * + * @param string $loaderKey loader configuration key + * @return callable + */ + protected function getLoader($loaderKey) { $serviceLoader = Configure::read($loaderKey); if (is_string($serviceLoader)) { $serviceLoader = new $serviceLoader(); } - return $serviceLoader($request, $response); + return $serviceLoader; } } From 62ba1f99675b715e9a5e9c0e21375e9d0df239de Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 17:32:54 -0200 Subject: [PATCH 193/685] Updated how to load the plugin --- Docs/Documentation/Installation.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index d4c284d27..6ecb830d8 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -49,10 +49,18 @@ Configure::write('OneTimePasswordAuthenticator.login', true); Load the Plugin ----------- -Ensure the Users Plugin is loaded in your config/bootstrap.php file +Ensure the Users Plugin is loaded in your src/Application.php file ``` -Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); + /** + * {@inheritdoc} + */ + public function bootstrap() + { + parent::bootstrap(); + + $this->addPlugin(\CakeDC\Users\Plugin::class); + } ``` Creating Required Tables From de5e44d152e0ff63ca74bdfcc0ba153d0173e144 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 17:55:43 -0200 Subject: [PATCH 194/685] Showing info about authentication/authorization plugin --- Docs/Documentation/Configuration.md | 47 ++++++++++++++++++----------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index e3a2bae56..9c7a5eed3 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -62,16 +62,21 @@ 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. +Loading the plugin and using the right configuration values will setup the Users plugin, +with authentication service, authorization service, and the OAuth components for your application. + +This plugin uses by default the new [cakephp/authentication](https://github.com/cakephp/authentication) +and [cakephp/authorization](https://github.com/cakephp/authorization) plugins we suggest you to take a look +into their documentation for more information. + +Most authentication/authorization configuration is defined at 'Auth' key, for example +if you don't want the plugin to autoload the authorization service, you could do: -If you prefer to setup AuthComponent by yourself, you'll need to load AuthComponent before UsersAuthComponent -and set ``` -Configure::write('Users.auth', false); +Configure::write('Auth.Authorization.enable', false) ``` -Interesting UsersAuthComponent options and defaults +Interesting Users 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 @@ -81,8 +86,6 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use '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, @@ -114,20 +117,28 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'active' => true, ], ], -// default configuration used to auto-load the Auth Component, override to change the way Auth works + //Default authentication/authorization setup 'Auth' => [ - 'authenticate' => [ - 'all' => [ - 'finder' => 'active', - ], - 'CakeDC/Auth.RememberMe', - 'Form', + 'Authentication' => [ + 'serviceLoader' => \CakeDC\Users\Loader\AuthenticationServiceLoader::class ], - 'authorize' => [ - 'CakeDC/Auth.Superuser', - 'CakeDC/Auth.SimpleRbac', + 'AuthenticationComponent' => [...], + 'Authenticators' => [...], + 'Identifiers' => [...], + "Authorization" => [ + 'enable' => true, + 'loadAuthorizationMiddleware' => true, + 'loadRbacMiddleware' => false, + 'serviceLoader' => \CakeDC\Users\Loader\AuthorizationServiceLoader::class ], + 'AuthorizationMiddleware' => [...], + 'AuthorizationComponent' => [...], + 'RbacMiddleware' => [...], + 'SocialLoginFailure' => [...], + 'FormLoginFailure' => [...] ], + 'SocialAuthMiddleware' => [...], + 'OAuth' => [...] ]; ``` From acf53ac47b9b016b30c9dcca98410f2c0d5d8bd9 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 18:43:03 -0200 Subject: [PATCH 195/685] document authenticators and authentication component --- src/Loader/AuthenticationServiceLoader.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Loader/AuthenticationServiceLoader.php b/src/Loader/AuthenticationServiceLoader.php index 7eb819606..7bed483fe 100644 --- a/src/Loader/AuthenticationServiceLoader.php +++ b/src/Loader/AuthenticationServiceLoader.php @@ -68,6 +68,7 @@ protected function loadIdentifiers($service) protected function loadAuthenticators($service) { $authenticators = Configure::read('Auth.Authenticators'); + foreach ($authenticators as $authenticator => $options) { if (is_numeric($authenticator)) { $authenticator = $options; From e3fa033f49fe2fdf49ad5be87cf6ba6f5bd28db1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 18:46:38 -0200 Subject: [PATCH 196/685] document authenticators and authentication component --- Docs/Documentation/Authentication.md | 128 +++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 Docs/Documentation/Authentication.md diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md new file mode 100644 index 000000000..b868d5be9 --- /dev/null +++ b/Docs/Documentation/Authentication.md @@ -0,0 +1,128 @@ +Authentication +============== + +Authentication Component +------------------------------- + +The default behavior is to load the authentication component at users controller, +defining the default urls for loginAction, loginRedirect, logoutRedirect but not requiring +the request to have a identity. + +If you prefer to load the component yourself you can set 'Auth.AuthenticationComponent.load': + +``` +Configure:write('Auth.AuthenticationComponent.load', false); +``` + +And load the component at any controller: + +``` +$authenticationConfig = Configure::read('Auth.AuthenticationComponent'); +$this->loadComponent('Authentication.Authentication', $authenticationConfig); +$user = $this->Authentication->getIdentity(); +``` +The default configuration for Auth.AuthenticationComponent is: + +``` +[ + 'load' => true, + 'loginAction' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + 'prefix' => false, + ], + 'logoutRedirect' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + 'prefix' => false, + ], + 'loginRedirect' => '/', + 'requireIdentity' => false +] +``` + +[Check the component options at the it's source code for more infomation](https://github.com/cakephp/authentication/blob/master/src/Controller/Component/AuthenticationComponent.php#L38) + +Authenticators +-------------- + +The cakephp/authentication plugin provider the main structure for the authenticators used in this plugin, +we also use some custom authenticators to work with social providers, reCaptcha and cookie. The default +list of authenticators includes: + +- 'Authentication.Session' +- 'CakeDC/Auth.Form' +- 'Authentication.Token' +- 'CakeDC/Auth.Cookie' +- 'CakeDC/Users.Social'//Works with SocialAuthMiddleware +- 'CakeDC/Users.SocialPendingEmail' + +**If you enable 'OneTimePasswordAuthenticator.login' we also load the CakeDC/Auth.TwoFactor** + +These authenticators should be enough for your application, but you easily customize it +setting the Auth.Authenticators config key. + +For example if you add JWT authenticator you can set: + +``` +$authenticators = Configure::read('Auth.Authenticators'); +$authenticators['Authentication.Jwt'] = [ + 'queryParam' => 'token', + 'skipGoogleVerify' => true, +]; +Configure::write('Auth.Authenticators', $authenticators); + +``` +**You may have noticed the 'skipGoogleVerify' option, this option is used to identify if a authenticator should skip +the two factor flow** + + +The default configuration for Auth.Authenticators is: +``` +[ + 'Authentication.Session' => [ + 'skipGoogleVerify' => true, + 'sessionKey' => 'Auth', + ], + 'CakeDC/Auth.Form' => [ + 'urlChecker' => 'Authentication.CakeRouter', + 'loginUrl' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + 'prefix' => false, + ] + ], + 'Authentication.Token' => [ + 'skipGoogleVerify' => true, + 'header' => null, + 'queryParam' => 'api_key', + 'tokenPrefix' => null, + ], + 'CakeDC/Auth.Cookie' => [ + 'skipGoogleVerify' => true, + 'rememberMeField' => 'remember_me', + 'cookie' => [ + 'expires' => '1 month', + 'httpOnly' => true, + ], + 'urlChecker' => 'Authentication.CakeRouter', + 'loginUrl' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + 'prefix' => false, + ] + ], + 'CakeDC/Users.Social' => [ + 'skipGoogleVerify' => true, + ], + 'CakeDC/Users.SocialPendingEmail' => [ + 'skipGoogleVerify' => true, + ] +] +``` + +Check the documentation for [authenticators](https://github.com/cakephp/authentication/blob/master/docs/Authenticators.md) From 1966a8c79e4133d91817d3a9aadaf7cd5f46e5b2 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 18:48:18 -0200 Subject: [PATCH 197/685] making sure files has copyright --- Docs/Documentation/Authentication.md | 48 +--------------------------- 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index b868d5be9..254fe3551 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -79,50 +79,4 @@ Configure::write('Auth.Authenticators', $authenticators); the two factor flow** -The default configuration for Auth.Authenticators is: -``` -[ - 'Authentication.Session' => [ - 'skipGoogleVerify' => true, - 'sessionKey' => 'Auth', - ], - 'CakeDC/Auth.Form' => [ - 'urlChecker' => 'Authentication.CakeRouter', - 'loginUrl' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - 'prefix' => false, - ] - ], - 'Authentication.Token' => [ - 'skipGoogleVerify' => true, - 'header' => null, - 'queryParam' => 'api_key', - 'tokenPrefix' => null, - ], - 'CakeDC/Auth.Cookie' => [ - 'skipGoogleVerify' => true, - 'rememberMeField' => 'remember_me', - 'cookie' => [ - 'expires' => '1 month', - 'httpOnly' => true, - ], - 'urlChecker' => 'Authentication.CakeRouter', - 'loginUrl' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - 'prefix' => false, - ] - ], - 'CakeDC/Users.Social' => [ - 'skipGoogleVerify' => true, - ], - 'CakeDC/Users.SocialPendingEmail' => [ - 'skipGoogleVerify' => true, - ] -] -``` - -Check the documentation for [authenticators](https://github.com/cakephp/authentication/blob/master/docs/Authenticators.md) +See the full Auth.Authenticators at config/users.php \ No newline at end of file From 2f8280532a226b0e0969ff81d63e1981f7c42534 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 18:55:36 -0200 Subject: [PATCH 198/685] document identifiers --- Docs/Documentation/Authentication.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 254fe3551..d7b14791d 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -79,4 +79,28 @@ Configure::write('Auth.Authenticators', $authenticators); the two factor flow** -See the full Auth.Authenticators at config/users.php \ No newline at end of file +See the full Auth.Authenticators at config/users.php + +Identifiers +----------- +The identifies are defined to work correctly with the default authenticators, we are using these identifiers: + +- Authentication.Password, for Form authenticator +- CakeDC/Users.Social, for Social and SocialPendingEmail authenticators +- Authentication.Token, for TokenAuthenticator + +As you add more authenticators you may need to add identifiers, please check identifiers available at +[official documentation](https://github.com/cakephp/authentication/blob/master/docs/Identifiers.md) + +The default value for Auth.Identifiers is: +``` +[ + 'Authentication.Password' => [], + "CakeDC/Users.Social" => [ + 'authFinder' => 'all' + ], + 'Authentication.Token' => [ + 'tokenField' => 'api_token' + ] +] +``` From f6d771b08ad226999af748971780c4a0c6db2b14 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 18:59:03 -0200 Subject: [PATCH 199/685] Saying when authenticators are loaded --- Docs/Documentation/Authentication.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index d7b14791d..6964021c8 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -78,7 +78,9 @@ Configure::write('Auth.Authenticators', $authenticators); **You may have noticed the 'skipGoogleVerify' option, this option is used to identify if a authenticator should skip the two factor flow** - +The authenticators are loaded by \CakeDC\Users\Loader\AuthenticationServiceLoader class at bootstrap step +of this plugin. + See the full Auth.Authenticators at config/users.php Identifiers @@ -104,3 +106,5 @@ The default value for Auth.Identifiers is: ] ] ``` +The identifiers are loaded by \CakeDC\Users\Loader\AuthenticationServiceLoader class at bootstrap step +of this plugin. \ No newline at end of file From 84200f2d242a5f9305f5923c698da45d92d772b4 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 19:01:17 -0200 Subject: [PATCH 200/685] Saying when authenticators/identifiers are loaded --- Docs/Documentation/Authentication.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 6964021c8..a03ddc345 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -78,8 +78,8 @@ Configure::write('Auth.Authenticators', $authenticators); **You may have noticed the 'skipGoogleVerify' option, this option is used to identify if a authenticator should skip the two factor flow** -The authenticators are loaded by \CakeDC\Users\Loader\AuthenticationServiceLoader class at bootstrap step -of this plugin. +The authenticators are loaded by \CakeDC\Users\Loader\AuthenticationServiceLoader class at load authentication +service method from plugin object. See the full Auth.Authenticators at config/users.php @@ -100,11 +100,13 @@ The default value for Auth.Identifiers is: 'Authentication.Password' => [], "CakeDC/Users.Social" => [ 'authFinder' => 'all' - ], + ], at load authentication + service step method from plugin object 'Authentication.Token' => [ 'tokenField' => 'api_token' ] ] ``` -The identifiers are loaded by \CakeDC\Users\Loader\AuthenticationServiceLoader class at bootstrap step -of this plugin. \ No newline at end of file +The identifiers are loaded by \CakeDC\Users\Loader\AuthenticationServiceLoader class at load authentication +service method from plugin object. + From 05cfe669eef52bc0cd8a5ee2ab391bd65c5fe1a9 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 19:16:16 -0200 Subject: [PATCH 201/685] doc how to change the authentication loader --- Docs/Documentation/Authentication.md | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index a03ddc345..4e6916098 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -110,3 +110,43 @@ The default value for Auth.Identifiers is: The identifiers are loaded by \CakeDC\Users\Loader\AuthenticationServiceLoader class at load authentication service method from plugin object. +Authentication Service Loader +----------------------------- +To make integration with cakephp/authentication easier we load the the authenticators and identifiers +defined at Auth configuration and other components to work with social provider, two-factor authentication. + +If the configuration is not enough for your project you may create a custom loader extending the +default provided. + +- Create file src/Loader/AppAuthenticationServiceLoader.php + +``` +loadAuthenticator('MyCustom', []); + } + } +} +``` +- Change the authentication service loader: + +``` +Configure::write('Authentication.serviceLoader', \CakeDC\Users\Loader\AuthenticationServiceLoader::class); +``` \ No newline at end of file From bb53eb88165e8d59a5ed0fabe3315844b0c57a4b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 19:24:55 -0200 Subject: [PATCH 202/685] this plugin uses cakephp/authentication --- Docs/Documentation/Authentication.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 4e6916098..a5928b08f 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -1,5 +1,9 @@ Authentication ============== +This component uses the new plugin for authentication [cakephp/authentication](https://github.com/cakephp/authentication/) +instead of CakePHP Authentication component, but the default configuration should be enough for your +projects. We tried to allow you to start quickly without the need to configure a lot of thing and also +allow you to configure as much as possible. Authentication Component ------------------------------- From 9fc9a6eed3323eabe3696e7f178afaac2c0578a3 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 19:37:19 -0200 Subject: [PATCH 203/685] fixed text --- Docs/Documentation/Authentication.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index a5928b08f..2ece745c3 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -1,12 +1,12 @@ Authentication ============== This component uses the new plugin for authentication [cakephp/authentication](https://github.com/cakephp/authentication/) -instead of CakePHP Authentication component, but the default configuration should be enough for your +instead of CakePHP Authentication component, but don't worry, the default configuration should be enough for your projects. We tried to allow you to start quickly without the need to configure a lot of thing and also allow you to configure as much as possible. Authentication Component -------------------------------- +------------------------ The default behavior is to load the authentication component at users controller, defining the default urls for loginAction, loginRedirect, logoutRedirect but not requiring From 58ced5a2dc68c0c8f8ec8beaedbd67fa3e6578d5 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 20:07:25 -0200 Subject: [PATCH 204/685] Don't load simple rbac middleware we use RbacPolicy --- src/Loader/MiddlewareQueueLoader.php | 10 ++----- tests/TestCase/PluginTest.php | 42 +--------------------------- 2 files changed, 3 insertions(+), 49 deletions(-) diff --git a/src/Loader/MiddlewareQueueLoader.php b/src/Loader/MiddlewareQueueLoader.php index 6e2479e0c..1d49d32d1 100644 --- a/src/Loader/MiddlewareQueueLoader.php +++ b/src/Loader/MiddlewareQueueLoader.php @@ -110,14 +110,8 @@ protected function loadAuthorizationMiddleware(MiddlewareQueue $middlewareQueue, return $middlewareQueue; } - if (Configure::read('Auth.Authorization.loadAuthorizationMiddleware') !== false) { - $middlewareQueue->add(new AuthorizationMiddleware($plugin, Configure::read('Auth.AuthorizationMiddleware'))); - $middlewareQueue->add(new RequestAuthorizationMiddleware()); - } - - if (Configure::read('Auth.Authorization.loadRbacMiddleware') !== false) { - $middlewareQueue->add(new RbacMiddleware(null, Configure::read('Auth.RbacMiddleware'))); - } + $middlewareQueue->add(new AuthorizationMiddleware($plugin, Configure::read('Auth.AuthorizationMiddleware'))); + $middlewareQueue->add(new RequestAuthorizationMiddleware()); return $middlewareQueue; } diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 753eae330..337246ad6 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -25,7 +25,6 @@ use CakeDC\Auth\Authenticator\FormAuthenticator; use CakeDC\Auth\Authenticator\TwoFactorAuthenticator; use CakeDC\Auth\Middleware\OneTimePasswordAuthenticatorMiddleware; -use CakeDC\Auth\Middleware\RbacMiddleware; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; use CakeDC\Users\Plugin; @@ -52,8 +51,6 @@ public function testMiddleware() Configure::write('Users.Social.login', true); Configure::write('OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', true); - Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); - Configure::write('Auth.Authorization.loadRbacMiddleware', false); $plugin = new Plugin(); @@ -79,8 +76,6 @@ public function testMiddlewareAuthorizationMiddlewareAndRbacMiddleware() Configure::write('Users.Social.login', true); Configure::write('OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', true); - Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); - Configure::write('Auth.Authorization.loadRbacMiddleware', true); $plugin = new Plugin(); @@ -93,34 +88,7 @@ public function testMiddlewareAuthorizationMiddlewareAndRbacMiddleware() $this->assertInstanceOf(OneTimePasswordAuthenticatorMiddleware::class, $middleware->get(3)); $this->assertInstanceOf(AuthorizationMiddleware::class, $middleware->get(4)); $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->get(5)); - $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(6)); - $this->assertEquals(7, $middleware->count()); - } - - /** - * testMiddleware - * - * @return void - */ - public function testMiddlewareAuthorizationOnlyRbacMiddleware() - { - Configure::write('Users.Social.login', true); - Configure::write('OneTimePasswordAuthenticator.login', true); - Configure::write('Auth.Authorization.enable', true); - Configure::write('Auth.Authorization.loadAuthorizationMiddleware', false); - Configure::write('Auth.Authorization.loadRbacMiddleware', true); - - $plugin = new Plugin(); - - $middleware = new MiddlewareQueue(); - - $middleware = $plugin->middleware($middleware); - $this->assertInstanceOf(SocialAuthMiddleware::class, $middleware->get(0)); - $this->assertInstanceOf(SocialEmailMiddleware::class, $middleware->get(1)); - $this->assertInstanceOf(AuthenticationMiddleware::class, $middleware->get(2)); - $this->assertInstanceOf(OneTimePasswordAuthenticatorMiddleware::class, $middleware->get(3)); - $this->assertInstanceOf(RbacMiddleware::class, $middleware->get(4)); - $this->assertEquals(5, $middleware->count()); + $this->assertEquals(6, $middleware->count()); } /** @@ -133,8 +101,6 @@ public function testMiddlewareWithoutAuhorization() Configure::write('Users.Social.login', true); Configure::write('OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', false); - Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true);//ignore - Configure::write('Auth.Authorization.loadRbacMiddleware', true);//ignore $plugin = new Plugin(); @@ -158,8 +124,6 @@ public function testMiddlewareNotSocial() Configure::write('Users.Social.login', false); Configure::write('OneTimePasswordAuthenticator.login', true); Configure::write('Auth.Authorization.enable', true); - Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); - Configure::write('Auth.Authorization.loadRbacMiddleware', false); $plugin = new Plugin(); $middleware = new MiddlewareQueue(); @@ -181,8 +145,6 @@ public function testMiddlewareNotOneTimePasswordAuthenticator() Configure::write('Users.Social.login', true); Configure::write('OneTimePasswordAuthenticator.login', false); Configure::write('Auth.Authorization.enable', true); - Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); - Configure::write('Auth.Authorization.loadRbacMiddleware', false); $plugin = new Plugin(); $middleware = new MiddlewareQueue(); @@ -205,8 +167,6 @@ public function testMiddlewareNotGoogleAuthenticationAndNotSocial() Configure::write('Users.Social.login', false); Configure::write('OneTimePasswordAuthenticator.login', false); Configure::write('Auth.Authorization.enable', true); - Configure::write('Auth.Authorization.loadAuthorizationMiddleware', true); - Configure::write('Auth.Authorization.loadRbacMiddleware', false); $plugin = new Plugin(); $middleware = new MiddlewareQueue(); From 7752311fc7771a17775c811bd34db0e0ca4719a4 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 24 Nov 2018 20:08:08 -0200 Subject: [PATCH 205/685] Don't load simple rbac middleware we use RbacPolicy --- config/users.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/users.php b/config/users.php index a57bb0cc1..c1ebdca56 100644 --- a/config/users.php +++ b/config/users.php @@ -194,8 +194,6 @@ ], "Authorization" => [ 'enable' => true, - 'loadAuthorizationMiddleware' => true, - 'loadRbacMiddleware' => false, 'serviceLoader' => \CakeDC\Users\Loader\AuthorizationServiceLoader::class ], 'AuthorizationMiddleware' => [ From fc8378dd6ce7b6d45f8bd30ad2f14e04db905e7b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 25 Nov 2018 18:23:06 -0200 Subject: [PATCH 206/685] document authorization basics --- Docs/Documentation/Authorization.md | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Docs/Documentation/Authorization.md diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md new file mode 100644 index 000000000..6a2498b87 --- /dev/null +++ b/Docs/Documentation/Authorization.md @@ -0,0 +1,54 @@ +Authorization +============= +This component uses the new plugin for authorization [cakephp/authorization](https://github.com/cakephp/authorization/) +instead of CakePHP Authorization component, but don't worry, the default configuration should be enough for your +projects. We tried to allow you to start quickly without the need to configure a lot of things and also +allow you to configure as much as possible. + + +If you don't want the plugin to autoload setup authorization, you can do: +``` +Configure::write('Auth.Authorization.enabled', false); +``` + +Authorization Middleware +------------------------ +We load the RequestAuthorization and Authorization middleware with OrmResolver and RbacProvider(work with RequestAuthorizationMiddleware). + +The middleware accepts some additional configurations, you can do: +``` +Configure::write('Auth.AuthorizationMiddleware', $config); +``` + +The default configuration for authorization middleware is: +``` +[ + 'unauthorizedHandler' => [ + 'exceptions' => [ + 'MissingIdentityException' => 'Authorization\Exception\MissingIdentityException', + 'ForbiddenException' => 'Authorization\Exception\ForbiddenException', + ], + 'className' => 'Authorization.CakeRedirect', + 'url' => [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + ] + ] +], +``` + +You can check the configuration options available for authorization middleware at the +[official documentation](https://github.com/cakephp/authorization/blob/master/docs/Middleware.md) + + +Authorization Component +----------------------- +We autoload the authorization component at users controller using the default configuration, +if you don't want the plugin to autoload it, you can do: +``` +Configure::write('Auth.AuthorizationComponent.enabled', false); +``` + +You can check the configuration options available for authorization component at the +[official documentation](https://github.com/cakephp/authorization/blob/master/docs/Component.md) From cb23b371328fa01dbf0f79acd245c8d065d6c9e1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 25 Nov 2018 18:39:52 -0200 Subject: [PATCH 207/685] =?UTF-8?q?doc=20how=20we=20handle=20login=C2=A0re?= =?UTF-8?q?sult?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Docs/Documentation/Authentication.md | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 2ece745c3..706c874f9 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -114,6 +114,53 @@ The default value for Auth.Identifiers is: The identifiers are loaded by \CakeDC\Users\Loader\AuthenticationServiceLoader class at load authentication service method from plugin object. + +Handling Login Result +--------------------- +For both form login and social login we use a base component 'CakeDC/Users.Login' to handle login, +it check the result of authentication service to redirect user to a internal page or show an authentication +error. It provide some error messages for specific authentication result status, please check the config/users.php file. + +To use a custom component to handle the login you could do: +``` +Configure::write('Auth.SocialLoginFailure.component', 'MyLoginA'); +Configure::write('Auth.FormLoginFailure.component', 'MyLoginB'); +``` + +The default configuration are: +``` +[ + ... + 'Auth' => [ + ... + 'SocialLoginFailure' => [ + 'component' => 'CakeDC/Users.Login', + 'defaultMessage' => __d('CakeDC/Users', 'Could not proceed with social account. Please try again'), + 'messages' => [ + 'FAILURE_USER_NOT_ACTIVE' => __d( + 'CakeDC/Users', + 'Your user has not been validated yet. Please check your inbox for instructions' + ), + 'FAILURE_ACCOUNT_NOT_ACTIVE' => __d( + 'CakeDC/Users', + 'Your social account has not been validated yet. Please check your inbox for instructions' + ) + ], + 'targetAuthenticator' => 'CakeDC\Users\Authenticator\SocialAuthenticator' + ], + 'FormLoginFailure' => [ + 'component' => 'CakeDC/Users.Login', + 'defaultMessage' => __d('CakeDC/Users', 'Username or password is incorrect'), + 'messages' => [ + 'FAILURE_INVALID_RECAPTCHA' => __d('CakeDC/Users', 'Invalid reCaptcha'), + ], + 'targetAuthenticator' => 'CakeDC\Auth\Authenticator\FormAuthenticator' + ] + ... + ] +] +``` + Authentication Service Loader ----------------------------- To make integration with cakephp/authentication easier we load the the authenticators and identifiers From 98ab3c1c040ba014501910f8a579062ce3c2f2a1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 25 Nov 2018 18:50:32 -0200 Subject: [PATCH 208/685] linking Authentication/Authorization config page --- Docs/Documentation/Authentication.md | 2 +- Docs/Documentation/Authorization.md | 2 +- Docs/Documentation/Configuration.md | 37 ++++++---------------------- config/users.php | 8 ------ 4 files changed, 9 insertions(+), 40 deletions(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 706c874f9..75f71dd56 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -1,6 +1,6 @@ Authentication ============== -This component uses the new plugin for authentication [cakephp/authentication](https://github.com/cakephp/authentication/) +This plugin uses the new plugin for authentication [cakephp/authentication](https://github.com/cakephp/authentication/) instead of CakePHP Authentication component, but don't worry, the default configuration should be enough for your projects. We tried to allow you to start quickly without the need to configure a lot of thing and also allow you to configure as much as possible. diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md index 6a2498b87..b56cc8aa0 100644 --- a/Docs/Documentation/Authorization.md +++ b/Docs/Documentation/Authorization.md @@ -1,6 +1,6 @@ Authorization ============= -This component uses the new plugin for authorization [cakephp/authorization](https://github.com/cakephp/authorization/) +This plugin uses the new plugin for authorization [cakephp/authorization](https://github.com/cakephp/authorization/) instead of CakePHP Authorization component, but don't worry, the default configuration should be enough for your projects. We tried to allow you to start quickly without the need to configure a lot of things and also allow you to configure as much as possible. diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 9c7a5eed3..b769bea14 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -127,13 +127,10 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'Identifiers' => [...], "Authorization" => [ 'enable' => true, - 'loadAuthorizationMiddleware' => true, - 'loadRbacMiddleware' => false, 'serviceLoader' => \CakeDC\Users\Loader\AuthorizationServiceLoader::class ], 'AuthorizationMiddleware' => [...], 'AuthorizationComponent' => [...], - 'RbacMiddleware' => [...], 'SocialLoginFailure' => [...], 'FormLoginFailure' => [...] ], @@ -143,35 +140,15 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use ``` -Default Authenticate and Authorize Objects used ------------------------- +Authentication and Authorization +-------------------------------- -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 +This plugin uses the two new plugins cakephp/authentication and cakephp/authorization instead of +CakePHP Authentication component, but don't worry, the default configuration should be enough for your +projects. We tried to allow you to start quickly without the need to configure a lot of thing and also +allow you to configure as much as possible. -Default Authorization Behavior ------------------------------- -For authorization process this plugin loads two cakephp/authorization midlewares, -**AuthorizationMiddleware** and **RequestAuthorizationMiddleware** (used with **RbacPolicy**). - -#### Configure AuthorizationMiddleware - -You can configure AuthorizationMiddleware by setting 'Auth.AuthorizationMiddleware' config, -check available options at https://github.com/cakephp/authorization/blob/master/docs/Middleware.md - -#### Additional configurations - -* **Auth.Authorization.enable:** defaults to true, enable authorization and try to load needed middlewares -* **Auth.Authorization.loadAuthorizationMiddleware:** defaults to true, load AuthorizationMiddleware and RequestAuthorizationMiddleware (used with RbacPolicy) -* **Auth.Authorization.loadRbacMiddleware:** defaults to false, if you don't want to use cakephp/authorization but want to -use Rbac permissions, set this config to true. +To learn more about it please check the configurations for [Authentication](Authentication.md) and [Authorization](Authorization.md) ## Using the user's email to login diff --git a/config/users.php b/config/users.php index c1ebdca56..cd38a0f6a 100644 --- a/config/users.php +++ b/config/users.php @@ -213,14 +213,6 @@ 'AuthorizationComponent' => [ 'enabled' => true, ], - 'RbacMiddleware' => [ - 'unauthorizedRedirect' => [ - 'prefix' => false, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - ] - ], 'SocialLoginFailure' => [ 'component' => 'CakeDC/Users.Login', 'defaultMessage' => __d('CakeDC/Users', 'Could not proceed with social account. Please try again'), From f8d281fb34d2791acdc6b2327616c32c6964c233 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 25 Nov 2018 19:01:59 -0200 Subject: [PATCH 209/685] doc login with email --- Docs/Documentation/Configuration.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index b769bea14..a03f10e40 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -153,10 +153,13 @@ To learn more about it please check the configurations for [Authentication](Auth ## 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 + +* Change the Password identifier fields configuration to let it use the email instead of the username for user identify. Add this to your Application class, after CakeDC/Users Plugin is loaded. ```php -Configure::write('Auth.authenticate.Form.fields.username', 'email'); + $identifiers = Configure::read('Auth.Identifiers'); + $identifiers['Authentication.Password']['fields']['username'] = 'email'; + Configure::write('Auth.Identifiers', $identifiers); ``` * 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 From 4e97b787bf2f54652b884364729f87f0c49ffd21 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 25 Nov 2018 19:03:36 -0200 Subject: [PATCH 210/685] linking Authentication/Authorization config page --- Docs/Home.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Docs/Home.md b/Docs/Home.md index a3b35a60c..0a17bb3bc 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -13,9 +13,10 @@ Documentation * [Overview](Documentation/Overview.md) * [Installation](Documentation/Installation.md) * [Configuration](Documentation/Configuration.md) +* [Authentication](Documentation/Authentication.md) +* [Authorization](Documentation/Authorization.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) * [Intercept Login Action](Documentation/InterceptLoginAction.md) * [SocialAuthenticate](Documentation/SocialAuthenticate.md) * [Google Authenticator](Documentation/Two-Factor-Authenticator.md) From 27585b014fa0961ddea64a8869d4744a6501ff70 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 25 Nov 2018 19:55:52 -0200 Subject: [PATCH 211/685] improved social authentication doc --- Docs/Documentation/SocialAuthenticate.md | 32 ++++++++++++++++++++++-- Docs/Home.md | 2 +- config/users.php | 7 ------ 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index 937039366..0ea60b4a2 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -1,5 +1,5 @@ -SocialAuthenticate -============= +SocialAuthentication +==================== We currently support the following providers to perform login as well as to link an existing account: @@ -95,3 +95,31 @@ $this->addBehavior('CakeDC.Users/Social', [ ``` By default it will use `username` field. + + +Social Middlewares +------------------ +We provide two middleware to help us the integration with social providers, the SocialAuthMiddleware is +the main one, it is responsible to redirect the user to the social provider site and setup information +needed by the CakeDC/Users.Social authenticator. The second one SocialEmailMiddleware is used when social provider does +not returns user email. + +Social Authenticators +--------------------- +The social authentication works with cakephp/authentication, we have two authenticators they work +in combination with the two social middlewares: + - CakeDC/Users.Social, works with SocialAuthMiddleware + - CakeDC/Users.SocialPendingEmai, works with SocialEmailMiddleware + + +Social Indentifier +------------------ +The social identifier "CakeDC/Users.Social", works with data provider by both social authenticator, +it is responsible to find or create a user registry for the request social user data. +By default it fetch user data with finder 'all', but you can use a one if you need. Add this to your +Application class, after CakeDC/Users Plugin is loaded. +``` + $identifiers = Configure::read('Auth.Identifiers'); + $identifiers['CakeDC/Users.Social']['authFinder'] = 'customSocialAuth'; + Configure::write('Auth.Identifiers', $identifiers); +``` diff --git a/Docs/Home.md b/Docs/Home.md index 0a17bb3bc..a288af97e 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -18,7 +18,7 @@ Documentation * [SimpleRbacAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SimpleRbacAuthorize.md) * [SuperuserAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SuperuserAuthorize.md) * [Intercept Login Action](Documentation/InterceptLoginAction.md) -* [SocialAuthenticate](Documentation/SocialAuthenticate.md) +* [Social Authentication](Documentation/SocialAuthenticate.md) * [Google Authenticator](Documentation/Two-Factor-Authenticator.md) * [UserHelper](Documentation/UserHelper.md) * [Events](Documentation/Events.md) diff --git a/config/users.php b/config/users.php index cd38a0f6a..6ce86bfba 100644 --- a/config/users.php +++ b/config/users.php @@ -237,13 +237,6 @@ 'targetAuthenticator' => 'CakeDC\Auth\Authenticator\FormAuthenticator' ] ], - 'SocialAuthMiddleware' => [ - 'sessionAuthKey' => 'Auth', - 'locator' => [ - 'usernameField' => 'username', - 'authFinder' => 'all', - ] - ], 'OAuth' => [ 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'prefix' => null], 'providers' => [ From 38af696bd4e494c6411f1b07c03fda74383a1c8c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 25 Nov 2018 20:00:19 -0200 Subject: [PATCH 212/685] Link to auth plugin at social authentication page --- Docs/Documentation/SocialAuthenticate.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index 0ea60b4a2..cec986e93 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -1,5 +1,5 @@ -SocialAuthentication -==================== +Social Authentication +===================== We currently support the following providers to perform login as well as to link an existing account: @@ -12,6 +12,8 @@ We currently support the following providers to perform login as well as to link Please [contact us](https://cakedc.com/contact) if you need to support another provider. +The main source code for social integration is provided by ['CakeDC/auth' plugin](https://github.com/cakedc/auth) + Setup --------------------- From 06f1861c40a282b82244c7a818f6b43fa814a01a Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 25 Nov 2018 20:06:05 -0200 Subject: [PATCH 213/685] improved social authentication doc --- Docs/Documentation/SocialAuthenticate.md | 39 ++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index cec986e93..970dadb8b 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -125,3 +125,42 @@ Application class, after CakeDC/Users Plugin is loaded. $identifiers['CakeDC/Users.Social']['authFinder'] = 'customSocialAuth'; Configure::write('Auth.Identifiers', $identifiers); ``` + + +Handling Social Login Result +---------------------------- +We use a base component 'CakeDC/Users.Login' to handle tlogin, it check the result of authentication +service to redirect user to a internal page or show an authentication error. It provide some error messages for social login. +There are two custom message (Auth.SocialLoginFailure.messages) and one default message (Auth.SocialLoginFailure.defaultMessage). + + +To use a custom component to handle the login you could do: +``` +Configure::write('Auth.SocialLoginFailure.component', 'MyLoginA'); +``` + +The default configurations are: +``` +[ + ... + 'Auth' => [ + ... + 'SocialLoginFailure' => [ + 'component' => 'CakeDC/Users.Login', + 'defaultMessage' => __d('CakeDC/Users', 'Could not proceed with social account. Please try again'), + 'messages' => [ + 'FAILURE_USER_NOT_ACTIVE' => __d( + 'CakeDC/Users', + 'Your user has not been validated yet. Please check your inbox for instructions' + ), + 'FAILURE_ACCOUNT_NOT_ACTIVE' => __d( + 'CakeDC/Users', + 'Your social account has not been validated yet. Please check your inbox for instructions' + ) + ], + 'targetAuthenticator' => 'CakeDC\Users\Authenticator\SocialAuthenticator' + ], + ... + ] +] +``` \ No newline at end of file From 564ee44f8ddf5d833ebc456e45832541d7a41864 Mon Sep 17 00:00:00 2001 From: Jorge Gonzalez Date: Mon, 26 Nov 2018 08:43:45 +0000 Subject: [PATCH 214/685] typo --- Docs/Documentation/Authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 75f71dd56..bae4dd343 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -52,7 +52,7 @@ The default configuration for Auth.AuthenticationComponent is: Authenticators -------------- -The cakephp/authentication plugin provider the main structure for the authenticators used in this plugin, +The cakephp/authentication plugin provides the main structure for the authenticators used in this plugin, we also use some custom authenticators to work with social providers, reCaptcha and cookie. The default list of authenticators includes: From 3ccd7e352e313e880363128f03d6337591fb0ef0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 3 Dec 2018 10:21:30 -0200 Subject: [PATCH 215/685] change passsword form should work with put/post request --- src/Controller/Traits/PasswordManagementTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index ddd07b9c8..fd5469eff 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -56,7 +56,7 @@ public function changePassword() $redirect = $this->Auth->getConfig('loginAction'); } $this->set('validatePassword', $validatePassword); - if ($this->request->is('post')) { + if ($this->request->is(['post', 'put'])) { try { $validator = $this->getUsersTable()->validationPasswordConfirm(new Validator()); if (!empty($id)) { From 925d515d47d8c82a4104ee4db10dc47e67fc0ad6 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 3 Dec 2018 10:40:01 -0200 Subject: [PATCH 216/685] change passsword form should work with put/post request --- .../Traits/PasswordManagementTraitTest.php | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index f4d292765..bf1a2faae 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -50,7 +50,7 @@ public function tearDown() public function testChangePasswordHappy() { $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); - $this->_mockRequestPost(); + $this->_mockRequestPost(['post', 'put']); $this->_mockAuthLoggedIn(); $this->_mockFlash(); $this->Trait->request->expects($this->once()) @@ -78,7 +78,7 @@ public function testChangePasswordHappy() public function testChangePasswordWithError() { $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); - $this->_mockRequestPost(); + $this->_mockRequestPost(['post', 'put']); $this->_mockAuthLoggedIn(); $this->_mockFlash(); $this->Trait->request->expects($this->once()) @@ -101,7 +101,7 @@ public function testChangePasswordWithError() public function testChangePasswordWithAfterChangeEvent() { $this->assertEquals('12345', $this->table->get('00000000-0000-0000-0000-000000000001')->password); - $this->_mockRequestPost(); + $this->_mockRequestPost(['post', 'put']); $this->_mockAuthLoggedIn(); $this->_mockFlash(); $this->Trait->request->expects($this->once()) @@ -139,7 +139,7 @@ public function testChangePasswordWithSamePassword() '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', $this->table->get('00000000-0000-0000-0000-000000000006')->password ); - $this->_mockRequestPost(); + $this->_mockRequestPost(['post', 'put']); $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); $this->_mockFlash(); $this->Trait->request->expects($this->once()) @@ -162,7 +162,7 @@ public function testChangePasswordWithSamePassword() */ public function testChangePasswordWithEmptyCurrentPassword() { - $this->_mockRequestPost(); + $this->_mockRequestPost(['post', 'put']); $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); $this->_mockFlash(); $this->Trait->request->expects($this->once()) @@ -189,7 +189,7 @@ public function testChangePasswordWithWrongCurrentPassword() '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC', $this->table->get('00000000-0000-0000-0000-000000000006')->password ); - $this->_mockRequestPost(); + $this->_mockRequestPost(['post', 'put']); $this->_mockAuthLoggedIn(['id' => '00000000-0000-0000-0000-000000000006', 'password' => '$2y$10$IPPgJNSfvATsMBLbv/2r8OtpyTBibyM1g5GDxD4PivW9qBRwRkRbC']); $this->_mockFlash(); $this->Trait->request->expects($this->once()) @@ -212,7 +212,7 @@ public function testChangePasswordWithWrongCurrentPassword() */ public function testChangePasswordWithInvalidUser() { - $this->_mockRequestPost(); + $this->_mockRequestPost(['post', 'put']); $this->_mockAuthLoggedIn(['id' => '12312312-0000-0000-0000-000000000002', 'password' => 'invalid-pass']); $this->_mockFlash(); $this->Trait->request->expects($this->once()) @@ -234,7 +234,13 @@ public function testChangePasswordWithInvalidUser() */ public function testChangePasswordGetLoggedIn() { - $this->_mockRequestGet(); + $this->Trait->request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->setMethods(['is', 'referer', 'getData']) + ->getMock(); + $this->Trait->request->expects($this->any()) + ->method('is') + ->with(['post', 'put']) + ->will($this->returnValue(false)); $this->_mockAuthLoggedIn(); $this->Trait->expects($this->any()) ->method('set') From 822d29ecb73cdcbff428f7db6acc7fef53975e2e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 13 Dec 2018 17:24:54 -0200 Subject: [PATCH 217/685] Using superuser and rbac policy --- src/Loader/AuthorizationServiceLoader.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Loader/AuthorizationServiceLoader.php b/src/Loader/AuthorizationServiceLoader.php index 39887880d..962ac21b9 100644 --- a/src/Loader/AuthorizationServiceLoader.php +++ b/src/Loader/AuthorizationServiceLoader.php @@ -15,8 +15,10 @@ use Authorization\Policy\MapResolver; use Authorization\Policy\OrmResolver; use Authorization\Policy\ResolverCollection; +use CakeDC\Auth\Policy\CollectionPolicy; use CakeDC\Auth\Policy\RbacPolicy; use Cake\Http\ServerRequest; +use CakeDC\Auth\Policy\SuperuserPolicy; use Psr\Http\Message\ServerRequestInterface; class AuthorizationServiceLoader @@ -30,7 +32,13 @@ class AuthorizationServiceLoader public function __invoke(ServerRequestInterface $request) { $map = new MapResolver(); - $map->map(ServerRequest::class, RbacPolicy::class); + $map->map( + ServerRequest::class, + new CollectionPolicy([ + SuperuserPolicy::class, + RbacPolicy::class + ]) + ); $orm = new OrmResolver(); From ca892017b481ee3d4ffa14cb23cf75f16a70d005 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 13 Dec 2018 17:37:57 -0200 Subject: [PATCH 218/685] Doc authorization service loader --- Docs/Documentation/Authentication.md | 4 +-- Docs/Documentation/Authorization.md | 43 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 75f71dd56..6017997fc 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -163,7 +163,7 @@ The default configuration are: Authentication Service Loader ----------------------------- -To make integration with cakephp/authentication easier we load the the authenticators and identifiers +To make the integration with cakephp/authentication easier we load the authenticators and identifiers defined at Auth configuration and other components to work with social provider, two-factor authentication. If the configuration is not enough for your project you may create a custom loader extending the @@ -199,5 +199,5 @@ class AppAuthenticationServiceLoader extends AuthenticationServiceLoader - Change the authentication service loader: ``` -Configure::write('Authentication.serviceLoader', \CakeDC\Users\Loader\AuthenticationServiceLoader::class); +Configure::write('Authentication.serviceLoader', \App\Loader\AuthenticationServiceLoader::class); ``` \ No newline at end of file diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md index b56cc8aa0..069570a1e 100644 --- a/Docs/Documentation/Authorization.md +++ b/Docs/Documentation/Authorization.md @@ -52,3 +52,46 @@ Configure::write('Auth.AuthorizationComponent.enabled', false); You can check the configuration options available for authorization component at the [official documentation](https://github.com/cakephp/authorization/blob/master/docs/Component.md) + +Authorization Service Loader +----------------------------- +To make the integration with cakephp/authorization easier we load the resolvers OrmResolver and MapResolver. +The MapResolver resolves ServerRequest request object to check access permission using Superuser and Rbac policies. + +If the configuration is not enough for your project you may create a custom loader extending the +default provided. + +- Create file src/Loader/AppAuthorizationServiceLoader.php + +``` + Date: Mon, 17 Dec 2018 09:23:57 -0200 Subject: [PATCH 219/685] Change domain names in PO files to 'cake_d_c/users' #730 --- Docs/Documentation/Authentication.md | 6 +- Docs/Documentation/SocialAuthenticate.md | 2 +- config/users.php | 6 +- src/Controller/SocialAccountsController.php | 20 ++--- src/Controller/Traits/LinkSocialTrait.php | 4 +- src/Controller/Traits/LoginTrait.php | 2 +- .../Traits/OneTimePasswordVerifyTrait.php | 6 +- .../Traits/PasswordManagementTrait.php | 24 +++--- src/Controller/Traits/ProfileTrait.php | 4 +- src/Controller/Traits/RegisterTrait.php | 12 +-- src/Controller/Traits/SimpleCrudTrait.php | 12 +-- src/Controller/Traits/UserValidationTrait.php | 24 +++--- src/Mailer/UsersMailer.php | 6 +- src/Middleware/SocialAuthMiddleware.php | 4 +- src/Model/Behavior/AuthFinderBehavior.php | 2 +- src/Model/Behavior/LinkSocialBehavior.php | 2 +- src/Model/Behavior/PasswordBehavior.php | 14 ++-- src/Model/Behavior/RegisterBehavior.php | 6 +- src/Model/Behavior/SocialAccountBehavior.php | 8 +- src/Model/Behavior/SocialBehavior.php | 4 +- src/Model/Table/UsersTable.php | 6 +- src/Shell/UsersShell.php | 80 +++++++++---------- src/Template/Email/html/reset_password.ctp | 6 +- .../Email/html/social_account_validation.ctp | 6 +- src/Template/Email/html/validation.ctp | 6 +- src/Template/Email/text/reset_password.ctp | 4 +- .../Email/text/social_account_validation.ctp | 4 +- src/Template/Email/text/validation.ctp | 4 +- src/Template/Users/add.ctp | 20 ++--- src/Template/Users/change_password.ctp | 10 +-- src/Template/Users/edit.ctp | 34 ++++---- src/Template/Users/index.ctp | 26 +++--- src/Template/Users/login.ctp | 14 ++-- src/Template/Users/profile.ctp | 18 ++--- src/Template/Users/register.ctp | 18 ++--- src/Template/Users/request_reset_password.ctp | 4 +- .../Users/resend_token_validation.ctp | 6 +- src/Template/Users/social_email.ctp | 4 +- src/Template/Users/verify.ctp | 4 +- src/Template/Users/view.ctp | 52 ++++++------ src/View/Helper/UserHelper.php | 12 +-- .../Controller/Traits/LinkSocialTraitTest.php | 8 +- .../Controller/Traits/LoginTraitTest.php | 16 ++-- .../Controller/Traits/SocialTraitTest.php | 2 +- .../Middleware/SocialAuthMiddlewareTest.php | 4 +- .../Model/Behavior/LinkSocialBehaviorTest.php | 2 +- 46 files changed, 269 insertions(+), 269 deletions(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 6017997fc..c8d85c358 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -135,7 +135,7 @@ The default configuration are: ... 'SocialLoginFailure' => [ 'component' => 'CakeDC/Users.Login', - 'defaultMessage' => __d('CakeDC/Users', 'Could not proceed with social account. Please try again'), + 'defaultMessage' => __d('cake_d_c/users', 'Could not proceed with social account. Please try again'), 'messages' => [ 'FAILURE_USER_NOT_ACTIVE' => __d( 'CakeDC/Users', @@ -150,9 +150,9 @@ The default configuration are: ], 'FormLoginFailure' => [ 'component' => 'CakeDC/Users.Login', - 'defaultMessage' => __d('CakeDC/Users', 'Username or password is incorrect'), + 'defaultMessage' => __d('cake_d_c/users', 'Username or password is incorrect'), 'messages' => [ - 'FAILURE_INVALID_RECAPTCHA' => __d('CakeDC/Users', 'Invalid reCaptcha'), + 'FAILURE_INVALID_RECAPTCHA' => __d('cake_d_c/users', 'Invalid reCaptcha'), ], 'targetAuthenticator' => 'CakeDC\Auth\Authenticator\FormAuthenticator' ] diff --git a/Docs/Documentation/SocialAuthenticate.md b/Docs/Documentation/SocialAuthenticate.md index 970dadb8b..43fd5fb27 100644 --- a/Docs/Documentation/SocialAuthenticate.md +++ b/Docs/Documentation/SocialAuthenticate.md @@ -147,7 +147,7 @@ The default configurations are: ... 'SocialLoginFailure' => [ 'component' => 'CakeDC/Users.Login', - 'defaultMessage' => __d('CakeDC/Users', 'Could not proceed with social account. Please try again'), + 'defaultMessage' => __d('cake_d_c/users', 'Could not proceed with social account. Please try again'), 'messages' => [ 'FAILURE_USER_NOT_ACTIVE' => __d( 'CakeDC/Users', diff --git a/config/users.php b/config/users.php index 6ce86bfba..5dd7cbbc0 100644 --- a/config/users.php +++ b/config/users.php @@ -215,7 +215,7 @@ ], 'SocialLoginFailure' => [ 'component' => 'CakeDC/Users.Login', - 'defaultMessage' => __d('CakeDC/Users', 'Could not proceed with social account. Please try again'), + 'defaultMessage' => __d('cake_d_c/users', 'Could not proceed with social account. Please try again'), 'messages' => [ 'FAILURE_USER_NOT_ACTIVE' => __d( 'CakeDC/Users', @@ -230,9 +230,9 @@ ], 'FormLoginFailure' => [ 'component' => 'CakeDC/Users.Login', - 'defaultMessage' => __d('CakeDC/Users', 'Username or password is incorrect'), + 'defaultMessage' => __d('cake_d_c/users', 'Username or password is incorrect'), 'messages' => [ - 'FAILURE_INVALID_RECAPTCHA' => __d('CakeDC/Users', 'Invalid reCaptcha'), + 'FAILURE_INVALID_RECAPTCHA' => __d('cake_d_c/users', 'Invalid reCaptcha'), ], 'targetAuthenticator' => 'CakeDC\Auth\Authenticator\FormAuthenticator' ] diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index 6baaa0b84..de290fde3 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -47,16 +47,16 @@ 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')); + $this->Flash->success(__d('cake_d_c/users', 'Account validated successfully')); } else { - $this->Flash->error(__d('CakeDC/Users', 'Account could not be validated')); + $this->Flash->error(__d('cake_d_c/users', 'Account could not be validated')); } } catch (RecordNotFoundException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Invalid token and/or social account')); + $this->Flash->error(__d('cake_d_c/users', 'Invalid token and/or social account')); } catch (AccountAlreadyActiveException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Social Account already active')); + $this->Flash->error(__d('cake_d_c/users', 'Social Account already active')); } catch (\Exception $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Social Account could not be validated')); + $this->Flash->error(__d('cake_d_c/users', 'Social Account could not be validated')); } return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); @@ -75,16 +75,16 @@ public function resendValidation($provider, $reference) try { $result = $this->SocialAccounts->resendValidation($provider, $reference); if ($result) { - $this->Flash->success(__d('CakeDC/Users', 'Email sent successfully')); + $this->Flash->success(__d('cake_d_c/users', 'Email sent successfully')); } else { - $this->Flash->error(__d('CakeDC/Users', 'Email could not be sent')); + $this->Flash->error(__d('cake_d_c/users', 'Email could not be sent')); } } catch (RecordNotFoundException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Invalid account')); + $this->Flash->error(__d('cake_d_c/users', 'Invalid account')); } catch (AccountAlreadyActiveException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Social Account already active')); + $this->Flash->error(__d('cake_d_c/users', 'Social Account already active')); } catch (\Exception $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Email could not be resent')); + $this->Flash->error(__d('cake_d_c/users', 'Email could not be resent')); } return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index 59ef87713..40a6cbc99 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -49,7 +49,7 @@ public function linkSocial($alias = null) */ public function callbackLinkSocial($alias = null) { - $message = __d('CakeDC/Users', 'Could not associate account, please try again.'); + $message = __d('cake_d_c/users', 'Could not associate account, please try again.'); try { $server = (new ServiceFactory()) ->setRedirectUriField('callbackLinkSocialUri') @@ -72,7 +72,7 @@ public function callbackLinkSocial($alias = null) if ($user->getErrors()) { $this->Flash->error($message); } else { - $this->Flash->success(__d('CakeDC/Users', 'Social account was associated.')); + $this->Flash->success(__d('cake_d_c/users', 'Social account was associated.')); } } catch (\Exception $e) { $log = sprintf( diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index 636915136..33774539d 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -76,7 +76,7 @@ public function logout() } $this->request->getSession()->destroy(); - $this->Flash->success(__d('CakeDC/Users', 'You\'ve successfully logged out')); + $this->Flash->success(__d('cake_d_c/users', 'You\'ve successfully logged out')); $eventAfter = $this->dispatchEvent(Plugin::EVENT_AFTER_LOGOUT, ['user' => $user]); if (is_array($eventAfter->result)) { diff --git a/src/Controller/Traits/OneTimePasswordVerifyTrait.php b/src/Controller/Traits/OneTimePasswordVerifyTrait.php index 86792b6dd..19e84d5b6 100644 --- a/src/Controller/Traits/OneTimePasswordVerifyTrait.php +++ b/src/Controller/Traits/OneTimePasswordVerifyTrait.php @@ -67,7 +67,7 @@ public function verify() protected function isVerifyAllowed() { if (!Configure::read('OneTimePasswordAuthenticator.login')) { - $message = __d('CakeDC/Users', 'Please enable Google Authenticator first.'); + $message = __d('cake_d_c/users', 'Please enable Google Authenticator first.'); $this->Flash->error($message, 'default', [], 'auth'); return false; @@ -76,7 +76,7 @@ protected function isVerifyAllowed() $temporarySession = $this->request->getSession()->read(AuthenticationService::GOOGLE_VERIFY_SESSION_KEY); if (empty($temporarySession) || !isset($temporarySession['id'])) { - $message = __d('CakeDC/Users', 'Could not find user data'); + $message = __d('cake_d_c/users', 'Could not find user data'); $this->Flash->error($message, 'default', [], 'auth'); return false; @@ -140,7 +140,7 @@ protected function onPostVerifyCode($loginAction) if (!$codeVerified) { $this->request->getSession()->destroy(); - $message = __d('CakeDC/Users', 'Verification code is invalid. Try again'); + $message = __d('cake_d_c/users', 'Verification code is invalid. Try again'); $this->Flash->error($message, 'default', [], 'auth'); return $this->redirect($loginAction); diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 08818a106..f8656989b 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -50,7 +50,7 @@ public function changePassword() $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->Flash->error(__d('cake_d_c/users', 'User was not found')); $this->redirect($this->Authentication->getConfig('loginAction')); return; @@ -72,7 +72,7 @@ public function changePassword() ); if ($user->getErrors()) { - $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); + $this->Flash->error(__d('cake_d_c/users', 'Password could not be changed')); } else { $result = $this->getUsersTable()->changePassword($user); if ($result) { @@ -80,19 +80,19 @@ public function changePassword() if (!empty($event) && is_array($event->result)) { return $this->redirect($event->result); } - $this->Flash->success(__d('CakeDC/Users', 'Password has been changed successfully')); + $this->Flash->success(__d('cake_d_c/users', 'Password has been changed successfully')); return $this->redirect($redirect); } else { - $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); + $this->Flash->error(__d('cake_d_c/users', 'Password could not be changed')); } } } catch (UserNotFoundException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'User was not found')); + $this->Flash->error(__d('cake_d_c/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->Flash->error(__d('cake_d_c/users', 'Password could not be changed')); $this->log($exception->getMessage()); } } @@ -134,20 +134,20 @@ public function requestResetPassword() 'type' => 'password' ]); if ($resetUser) { - $msg = __d('CakeDC/Users', 'Please check your email to continue with password reset process'); + $msg = __d('cake_d_c/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'); + $msg = __d('cake_d_c/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)); + $this->Flash->error(__d('cake_d_c/users', 'User {0} was not found', $reference)); } catch (UserNotActiveException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'The user is not active')); + $this->Flash->error(__d('cake_d_c/users', 'The user is not active')); } catch (Exception $exception) { - $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); + $this->Flash->error(__d('cake_d_c/users', 'Token could not be reset')); $this->log($exception->getMessage()); } } @@ -171,7 +171,7 @@ public function resetOneTimePasswordAuthenticator($id = null) ->where(['id' => $id]); $query->execute(); - $message = __d('CakeDC/Users', 'Google Authenticator token was successfully reset'); + $message = __d('cake_d_c/users', 'Google Authenticator token was successfully reset'); $this->Flash->success($message, 'default'); } catch (\Exception $e) { $message = $e->getMessage(); diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index 6b50254da..17048ef37 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -50,11 +50,11 @@ public function profile($id = null) $isCurrentUser = true; } } catch (RecordNotFoundException $ex) { - $this->Flash->error(__d('CakeDC/Users', 'User was not found')); + $this->Flash->error(__d('cake_d_c/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')); + $this->Flash->error(__d('cake_d_c/users', 'Not authorized, please login first')); return $this->redirect($this->request->referer()); } diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index f493a63d1..c54bd2f0c 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -43,7 +43,7 @@ public function register() $identity = isset($identity) ? $identity : []; $userId = Hash::get($identity, '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')); + $this->Flash->error(__d('cake_d_c/users', 'You must log out to register a new user account')); return $this->redirect(Configure::read('Users.Profile.route')); } @@ -72,7 +72,7 @@ public function register() return $this->_afterRegister($userSaved); } else { $this->set(compact('user')); - $this->Flash->error(__d('CakeDC/Users', 'The user could not be saved')); + $this->Flash->error(__d('cake_d_c/users', 'The user could not be saved')); return; } @@ -89,14 +89,14 @@ public function register() } if (!$this->_validateRegisterPost()) { - $this->Flash->error(__d('CakeDC/Users', 'Invalid reCaptcha')); + $this->Flash->error(__d('cake_d_c/users', 'Invalid reCaptcha')); return; } $userSaved = $usersTable->register($user, $requestData, $options); if (!$userSaved) { - $this->Flash->error(__d('CakeDC/Users', 'The user could not be saved')); + $this->Flash->error(__d('cake_d_c/users', 'The user could not be saved')); return; } @@ -130,9 +130,9 @@ protected function _validateRegisterPost() protected function _afterRegister(EntityInterface $userSaved) { $validateEmail = (bool)Configure::read('Users.Email.validate'); - $message = __d('CakeDC/Users', 'You have registered successfully, please log in'); + $message = __d('cake_d_c/users', 'You have registered successfully, please log in'); if ($validateEmail) { - $message = __d('CakeDC/Users', 'Please validate your account before log in'); + $message = __d('cake_d_c/users', 'Please validate your account before log in'); } $event = $this->dispatchEvent(Plugin::EVENT_AFTER_REGISTER, [ 'user' => $userSaved diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php index 5b1e3b278..4f200f684 100644 --- a/src/Controller/Traits/SimpleCrudTrait.php +++ b/src/Controller/Traits/SimpleCrudTrait.php @@ -74,11 +74,11 @@ public function add() $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)); + $this->Flash->success(__d('cake_d_c/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)); + $this->Flash->error(__d('cake_d_c/users', 'The {0} could not be saved', $singular)); } /** @@ -104,11 +104,11 @@ public function edit($id = null) $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)); + $this->Flash->success(__d('cake_d_c/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)); + $this->Flash->error(__d('cake_d_c/users', 'The {0} could not be saved', $singular)); } /** @@ -128,9 +128,9 @@ public function delete($id = null) ]); $singular = Inflector::singularize(Inflector::humanize($tableAlias)); if ($table->delete($entity)) { - $this->Flash->success(__d('CakeDC/Users', 'The {0} has been deleted', $singular)); + $this->Flash->success(__d('cake_d_c/users', 'The {0} has been deleted', $singular)); } else { - $this->Flash->error(__d('CakeDC/Users', 'The {0} could not be deleted', $singular)); + $this->Flash->error(__d('cake_d_c/users', 'The {0} could not be deleted', $singular)); } return $this->redirect(['action' => 'index']); diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index d91ca41bf..c9106fadf 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -41,18 +41,18 @@ public function validate($type = null, $token = null) try { $result = $this->getUsersTable()->validate($token, 'activateUser'); if ($result) { - $this->Flash->success(__d('CakeDC/Users', 'User account validated successfully')); + $this->Flash->success(__d('cake_d_c/users', 'User account validated successfully')); } else { - $this->Flash->error(__d('CakeDC/Users', 'User account could not be validated')); + $this->Flash->error(__d('cake_d_c/users', 'User account could not be validated')); } } catch (UserAlreadyActiveException $exception) { - $this->Flash->error(__d('CakeDC/Users', 'User already active')); + $this->Flash->error(__d('cake_d_c/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->Flash->success(__d('cake_d_c/users', 'Reset password token was validated successfully')); $this->request->getSession()->write( Configure::read('Users.Key.Session.resetPasswordUserId'), $result->id @@ -60,20 +60,20 @@ public function validate($type = null, $token = null) return $this->redirect(['action' => 'changePassword']); } else { - $this->Flash->error(__d('CakeDC/Users', 'Reset password token could not be validated')); + $this->Flash->error(__d('cake_d_c/users', 'Reset password token could not be validated')); } break; default: - $this->Flash->error(__d('CakeDC/Users', 'Invalid validation type')); + $this->Flash->error(__d('cake_d_c/users', 'Invalid validation type')); } } catch (UserNotFoundException $ex) { - $this->Flash->error(__d('CakeDC/Users', 'Invalid token or user account already validated')); + $this->Flash->error(__d('cake_d_c/users', 'Invalid token or user account already validated')); } catch (TokenExpiredException $ex) { $event = $this->dispatchEvent(Plugin::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')); + $this->Flash->error(__d('cake_d_c/users', 'Token already expired')); } return $this->redirect(['action' => 'login']); @@ -108,16 +108,16 @@ public function resendTokenValidation() 'Token has been reset successfully. Please check your email.' )); } else { - $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); + $this->Flash->error(__d('cake_d_c/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)); + $this->Flash->error(__d('cake_d_c/users', 'User {0} was not found', $reference)); } catch (UserAlreadyActiveException $ex) { - $this->Flash->error(__d('CakeDC/Users', 'User {0} is already active', $reference)); + $this->Flash->error(__d('cake_d_c/users', 'User {0} is already active', $reference)); } catch (Exception $ex) { - $this->Flash->error(__d('CakeDC/Users', 'Token could not be reset')); + $this->Flash->error(__d('cake_d_c/users', 'Token could not be reset')); } } } diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index fa3457024..8bf50a2d9 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -30,7 +30,7 @@ protected function validation(EntityInterface $user) $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; // un-hide the token to be able to send it in the email content $user->setHidden(['password', 'token_expires', 'api_token']); - $subject = __d('CakeDC/Users', 'Your account validation link'); + $subject = __d('cake_d_c/users', 'Your account validation link'); $this ->setTo($user['email']) ->setSubject($firstName . $subject) @@ -48,7 +48,7 @@ protected function validation(EntityInterface $user) protected function resetPassword(EntityInterface $user) { $firstName = isset($user['first_name'])? $user['first_name'] . ', ' : ''; - $subject = __d('CakeDC/Users', '{0}Your reset password link', $firstName); + $subject = __d('cake_d_c/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']); @@ -71,7 +71,7 @@ protected function socialAccountValidation(EntityInterface $user, EntityInterfac { $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); + $subject = __d('cake_d_c/users', '{0}Your social account validation link', $firstName); $this ->setTo($user['email']) ->setSubject($subject) diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index e7060b89a..4f0e19fa0 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -62,7 +62,7 @@ protected function onAuthenticationException(ServerRequest $request, ResponseInt { $baseClassName = get_class($exception->getPrevious()); if ($baseClassName === MissingEmailException::class) { - $this->setErrorMessage($request, __d('CakeDC/Users', 'Please enter your email')); + $this->setErrorMessage($request, __d('cake_d_c/users', 'Please enter your email')); $request->getSession()->write( Configure::read('Users.Key.Session.social'), @@ -72,7 +72,7 @@ protected function onAuthenticationException(ServerRequest $request, ResponseInt return $this->responseWithActionLocation($response, 'socialEmail'); } - $this->setErrorMessage($request, __d('CakeDC/Users', 'Could not identify your account, please try again')); + $this->setErrorMessage($request, __d('cake_d_c/users', 'Could not identify your account, please try again')); return $this->responseWithActionLocation($response, 'login'); } diff --git a/src/Model/Behavior/AuthFinderBehavior.php b/src/Model/Behavior/AuthFinderBehavior.php index 2edd6c759..6cb706df1 100644 --- a/src/Model/Behavior/AuthFinderBehavior.php +++ b/src/Model/Behavior/AuthFinderBehavior.php @@ -45,7 +45,7 @@ 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')); + throw new \BadMethodCallException(__d('cake_d_c/users', 'Missing \'username\' in options data')); } $where = $query->clause('where') ?: []; $query diff --git a/src/Model/Behavior/LinkSocialBehavior.php b/src/Model/Behavior/LinkSocialBehavior.php index 66229ec42..6c788340d 100644 --- a/src/Model/Behavior/LinkSocialBehavior.php +++ b/src/Model/Behavior/LinkSocialBehavior.php @@ -50,7 +50,7 @@ public function linkSocialAccount(EntityInterface $user, $data) if ($socialAccount && $user->id !== $socialAccount->user_id) { $user->setErrors([ 'social_accounts' => [ - '_existsIn' => __d('CakeDC/Users', 'Social account already associated to another user') + '_existsIn' => __d('cake_d_c/users', 'Social account already associated to another user') ] ]); diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index c0fcd951a..fa522ec95 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -42,29 +42,29 @@ class PasswordBehavior extends BaseTokenBehavior public function resetToken($reference, array $options = []) { if (empty($reference)) { - throw new \InvalidArgumentException(__d('CakeDC/Users', "Reference cannot be null")); + throw new \InvalidArgumentException(__d('cake_d_c/users', "Reference cannot be null")); } $expiration = Hash::get($options, 'expiration'); if (empty($expiration)) { - throw new \InvalidArgumentException(__d('CakeDC/Users', "Token expiration cannot be empty")); + throw new \InvalidArgumentException(__d('cake_d_c/users', "Token expiration cannot be empty")); } $user = $this->_getUser($reference); if (empty($user)) { - throw new UserNotFoundException(__d('CakeDC/Users', "User not found")); + throw new UserNotFoundException(__d('cake_d_c/users', "User not found")); } if (Hash::get($options, 'checkActive')) { if ($user->active) { - throw new UserAlreadyActiveException(__d('CakeDC/Users', "User account already validated")); + throw new UserAlreadyActiveException(__d('cake_d_c/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")); + throw new UserNotActiveException(__d('cake_d_c/users', "User not active")); } } $user->updateToken($expiration); @@ -135,12 +135,12 @@ public function changePassword(EntityInterface $user) 'contain' => [] ]); } catch (RecordNotFoundException $e) { - throw new UserNotFoundException(__d('CakeDC/Users', "User not found")); + throw new UserNotFoundException(__d('cake_d_c/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')); + throw new WrongPasswordException(__d('cake_d_c/users', 'The current password does not match')); } if ($user->current_password === $user->password_confirm) { throw new WrongPasswordException(__d( diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 8ef6b8380..1fda6800c 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -87,10 +87,10 @@ public function validate($token, $callback = null) ->where(['token' => $token]) ->first(); if (empty($user)) { - throw new UserNotFoundException(__d('CakeDC/Users', "User not found for the given token and email.")); + throw new UserNotFoundException(__d('cake_d_c/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")); + throw new TokenExpiredException(__d('cake_d_c/users', "Token has already expired user with no token")); } if (!method_exists($this, $callback)) { return $user; @@ -109,7 +109,7 @@ public function validate($token, $callback = null) public function activateUser(EntityInterface $user) { if ($user->active) { - throw new UserAlreadyActiveException(__d('CakeDC/Users', "User account already validated")); + throw new UserAlreadyActiveException(__d('cake_d_c/users', "User account already validated")); } $user->activation_date = new \DateTime(); $user->token_expires = null; diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index ced7df8dc..d239e6e4b 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -99,10 +99,10 @@ public function validateAccount($provider, $reference, $token) if (!empty($socialAccount) && $socialAccount->token === $token) { if ($socialAccount->active) { - throw new AccountAlreadyActiveException(__d('CakeDC/Users', "Account already validated")); + throw new AccountAlreadyActiveException(__d('cake_d_c/users', "Account already validated")); } } else { - throw new RecordNotFoundException(__d('CakeDC/Users', "Account not found for the given token and email.")); + throw new RecordNotFoundException(__d('cake_d_c/users', "Account not found for the given token and email.")); } return $this->_activateAccount($socialAccount); @@ -126,10 +126,10 @@ public function resendValidation($provider, $reference) if (!empty($socialAccount)) { if ($socialAccount->active) { - throw new AccountAlreadyActiveException(__d('CakeDC/Users', "Account already validated")); + throw new AccountAlreadyActiveException(__d('cake_d_c/users', "Account already validated")); } } else { - throw new RecordNotFoundException(__d('CakeDC/Users', "Account not found for the given token and email.")); + throw new RecordNotFoundException(__d('cake_d_c/users', "Account not found for the given token and email.")); } return $this->sendSocialValidationEmail($socialAccount, $socialAccount->user); diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index f1bc95e41..677ae1ceb 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -80,7 +80,7 @@ public function socialLogin(array $data, array $options) $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)); + throw new InvalidArgumentException(__d('cake_d_c/users', 'Unable to login user with reference {0}', $reference)); } } else { $user = $existingAccount->user; @@ -119,7 +119,7 @@ protected function _createSocialUser($data, $options = []) $existingUser = null; $email = Hash::get($data, 'email'); if ($useEmail && empty($email)) { - throw new MissingEmailException(__d('CakeDC/Users', 'Email not present')); + throw new MissingEmailException(__d('cake_d_c/users', 'Email not present')); } else { $existingUser = $this->_table->find() ->where([$this->_table->aliasField('email') => $email]) diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index d36c543b7..13ee27d85 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -76,7 +76,7 @@ public function validationPasswordConfirm(Validator $validator) ->add('password', [ 'password_confirm_check' => [ 'rule' => ['compareWith', 'password_confirm'], - 'message' => __d('CakeDC/Users', 'Your password does not match your confirm password. Please try again'), + 'message' => __d('cake_d_c/users', 'Your password does not match your confirm password. Please try again'), 'allowEmpty' => false ]]); @@ -168,13 +168,13 @@ public function buildRules(RulesChecker $rules) { $rules->add($rules->isUnique(['username']), '_isUnique', [ 'errorField' => 'username', - 'message' => __d('CakeDC/Users', 'Username already exists') + 'message' => __d('cake_d_c/users', 'Username already exists') ]); if ($this->isValidateEmail) { $rules->add($rules->isUnique(['email']), '_isUnique', [ 'errorField' => 'email', - 'message' => __d('CakeDC/Users', 'Email already exists') + 'message' => __d('cake_d_c/users', 'Email already exists') ]); } diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index d93ab492a..782631f5a 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -55,33 +55,33 @@ public function initialize() public function getOptionParser() { $parser = parent::getOptionParser(); - $parser->setDescription(__d('CakeDC/Users', 'Utilities for CakeDC Users Plugin')) + $parser->setDescription(__d('cake_d_c/users', 'Utilities for CakeDC Users Plugin')) ->addSubcommand('activateUser', [ - 'help' => __d('CakeDC/Users', 'Activate an specific user') + 'help' => __d('cake_d_c/users', 'Activate an specific user') ]) ->addSubcommand('addSuperuser', [ - 'help' => __d('CakeDC/Users', 'Add a new superadmin user for testing purposes') + 'help' => __d('cake_d_c/users', 'Add a new superadmin user for testing purposes') ]) ->addSubcommand('addUser', [ - 'help' => __d('CakeDC/Users', 'Add a new user') + 'help' => __d('cake_d_c/users', 'Add a new user') ]) ->addSubcommand('changeRole', [ - 'help' => __d('CakeDC/Users', 'Change the role for an specific user') + 'help' => __d('cake_d_c/users', 'Change the role for an specific user') ]) ->addSubcommand('deactivateUser', [ - 'help' => __d('CakeDC/Users', 'Deactivate an specific user') + 'help' => __d('cake_d_c/users', 'Deactivate an specific user') ]) ->addSubcommand('deleteUser', [ - 'help' => __d('CakeDC/Users', 'Delete an specific user') + 'help' => __d('cake_d_c/users', 'Delete an specific user') ]) ->addSubcommand('passwordEmail', [ - 'help' => __d('CakeDC/Users', 'Reset the password via email') + 'help' => __d('cake_d_c/users', 'Reset the password via email') ]) ->addSubcommand('resetAllPasswords', [ - 'help' => __d('CakeDC/Users', 'Reset the password for all users') + 'help' => __d('cake_d_c/users', 'Reset the password for all users') ]) ->addSubcommand('resetPassword', [ - 'help' => __d('CakeDC/Users', 'Reset the password for an specific user') + 'help' => __d('cake_d_c/users', 'Reset the password for an specific user') ]) ->addOptions([ 'username' => ['short' => 'u', 'help' => 'The username for the new user'], @@ -130,12 +130,12 @@ public function resetAllPasswords() { $password = Hash::get($this->args, 0); if (empty($password)) { - $this->abort(__d('CakeDC/Users', 'Please enter a password.')); + $this->abort(__d('cake_d_c/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)); + $this->out(__d('cake_d_c/users', 'Password changed for all users')); + $this->out(__d('cake_d_c/users', 'New password: {0}', $password)); } /** @@ -153,17 +153,17 @@ 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.')); + $this->abort(__d('cake_d_c/users', 'Please enter a username.')); } if (empty($password)) { - $this->abort(__d('CakeDC/Users', 'Please enter a password.')); + $this->abort(__d('cake_d_c/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)); + $this->out(__d('cake_d_c/users', 'Password changed for user: {0}', $username)); + $this->out(__d('cake_d_c/users', 'New password: {0}', $password)); } /** @@ -181,17 +181,17 @@ 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.')); + $this->abort(__d('cake_d_c/users', 'Please enter a username.')); } if (empty($role)) { - $this->abort(__d('CakeDC/Users', 'Please enter a role.')); + $this->abort(__d('cake_d_c/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)); + $this->out(__d('cake_d_c/users', 'Role changed for user: {0}', $username)); + $this->out(__d('cake_d_c/users', 'New role: {0}', $savedUser->role)); } /** @@ -206,7 +206,7 @@ public function changeRole() public function activateUser() { $user = $this->_changeUserActive(true); - $this->out(__d('CakeDC/Users', 'User was activated: {0}', $user->username)); + $this->out(__d('cake_d_c/users', 'User was activated: {0}', $user->username)); } /** @@ -221,7 +221,7 @@ public function activateUser() public function deactivateUser() { $user = $this->_changeUserActive(false); - $this->out(__d('CakeDC/Users', 'User was de-activated: {0}', $user->username)); + $this->out(__d('cake_d_c/users', 'User was de-activated: {0}', $user->username)); } /** @@ -233,7 +233,7 @@ public function passwordEmail() { $reference = Hash::get($this->args, 0); if (empty($reference)) { - $this->abort(__d('CakeDC/Users', 'Please enter a username or email.')); + $this->abort(__d('cake_d_c/users', 'Please enter a username or email.')); } $resetUser = $this->Users->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), @@ -241,10 +241,10 @@ public function passwordEmail() 'sendEmail' => true, ]); if ($resetUser) { - $msg = __d('CakeDC/Users', 'Please ask the user to check the email to continue with password reset process'); + $msg = __d('cake_d_c/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'); + $msg = __d('cake_d_c/users', 'The password token could not be generated. Please try again'); $this->abort($msg); } } @@ -259,7 +259,7 @@ protected function _changeUserActive($active) { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->abort(__d('CakeDC/Users', 'Please enter a username.')); + $this->abort(__d('cake_d_c/users', 'Please enter a username.')); } $data = [ 'active' => $active @@ -305,20 +305,20 @@ protected function _createUser($template) if (!empty($savedUser)) { if ($savedUser->is_superuser) { - $this->out(__d('CakeDC/Users', 'Superuser added:')); + $this->out(__d('cake_d_c/users', 'Superuser added:')); } else { - $this->out(__d('CakeDC/Users', 'User added:')); + $this->out(__d('cake_d_c/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)); + $this->out(__d('cake_d_c/users', 'Id: {0}', $savedUser->id)); + $this->out(__d('cake_d_c/users', 'Username: {0}', $savedUser->username)); + $this->out(__d('cake_d_c/users', 'Email: {0}', $savedUser->email)); + $this->out(__d('cake_d_c/users', 'Role: {0}', $savedUser->role)); + $this->out(__d('cake_d_c/users', 'Password: {0}', $password)); } else { - $this->out(__d('CakeDC/Users', 'User could not be added:')); + $this->out(__d('cake_d_c/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))); + $this->out(__d('cake_d_c/users', 'Field: {0} Error: {1}', $field, implode(',', $error))); }); } } @@ -334,7 +334,7 @@ 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.')); + $this->abort(__d('cake_d_c/users', 'The user was not found.')); } $user = $this->Users->patchEntity($user, $data); collection($data)->filter(function ($value, $field) use ($user) { @@ -356,7 +356,7 @@ public function deleteUser() { $username = Hash::get($this->args, 0); if (empty($username)) { - $this->abort(__d('CakeDC/Users', 'Please enter a username.')); + $this->abort(__d('cake_d_c/users', 'Please enter a username.')); } $user = $this->Users->find()->where(['username' => $username])->first(); if (isset($this->Users->SocialAccounts)) { @@ -364,9 +364,9 @@ public function deleteUser() } $deleteUser = $this->Users->delete($user); if (!$deleteUser) { - $this->abort(__d('CakeDC/Users', 'The user {0} was not deleted. Please try again', $username)); + $this->abort(__d('cake_d_c/users', 'The user {0} was not deleted. Please try again', $username)); } - $this->out(__d('CakeDC/Users', 'The user {0} was deleted successfully', $username)); + $this->out(__d('cake_d_c/users', 'The user {0} was deleted successfully', $username)); } /** diff --git a/src/Template/Email/html/reset_password.ctp b/src/Template/Email/html/reset_password.ctp index a51955d83..be4a047c4 100644 --- a/src/Template/Email/html/reset_password.ctp +++ b/src/Template/Email/html/reset_password.ctp @@ -18,10 +18,10 @@ $activationUrl = [ ]; ?>

- , + ,

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

- , + ,

diff --git a/src/Template/Email/html/social_account_validation.ctp b/src/Template/Email/html/social_account_validation.ctp index 224a49e2a..7b56ea3ad 100644 --- a/src/Template/Email/html/social_account_validation.ctp +++ b/src/Template/Email/html/social_account_validation.ctp @@ -11,11 +11,11 @@ ?>

- , + ,

true, 'plugin' => 'CakeDC/Users', @@ -36,5 +36,5 @@ ) ?>

- , + ,

diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp index 366453c4a..be9b240cc 100644 --- a/src/Template/Email/html/validation.ctp +++ b/src/Template/Email/html/validation.ctp @@ -18,10 +18,10 @@ $activationUrl = [ ]; ?>

- , + ,

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

- , + ,

diff --git a/src/Template/Email/text/reset_password.ctp b/src/Template/Email/text/reset_password.ctp index c7f9e8c36..f4e5d13c6 100644 --- a/src/Template/Email/text/reset_password.ctp +++ b/src/Template/Email/text/reset_password.ctp @@ -17,7 +17,7 @@ $activationUrl = [ 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 index e75fb5a76..114f0876d 100644 --- a/src/Template/Email/text/social_account_validation.ctp +++ b/src/Template/Email/text/social_account_validation.ctp @@ -19,7 +19,7 @@ $activationUrl = [ $socialAccount['token'], ]; ?> -, +, Url->build($activationUrl) ) ?> -, +, diff --git a/src/Template/Email/text/validation.ctp b/src/Template/Email/text/validation.ctp index 74b49dea2..448bba703 100644 --- a/src/Template/Email/text/validation.ctp +++ b/src/Template/Email/text/validation.ctp @@ -17,7 +17,7 @@ $activationUrl = [ isset($token) ? $token : '' ]; ?> -, +, Url->build($activationUrl) ) ?> -, +, diff --git a/src/Template/Users/add.ctp b/src/Template/Users/add.ctp index 37115c609..e9d12b1e5 100644 --- a/src/Template/Users/add.ctp +++ b/src/Template/Users/add.ctp @@ -10,27 +10,27 @@ */ ?>
-

+

    -
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • +
  • Html->link(__d('cake_d_c/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('username', ['label' => __d('cake_d_c/users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('cake_d_c/users', 'Email')]); + echo $this->Form->control('password', ['label' => __d('cake_d_c/users', 'Password')]); + echo $this->Form->control('first_name', ['label' => __d('cake_d_c/users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('cake_d_c/users', 'Last name')]); echo $this->Form->control('active', [ 'type' => 'checkbox', - 'label' => __d('CakeDC/Users', 'Active') + 'label' => __d('cake_d_c/users', 'Active') ]); ?>
- Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->button(__d('cake_d_c/users', 'Submit')) ?> Form->end() ?>
diff --git a/src/Template/Users/change_password.ctp b/src/Template/Users/change_password.ctp index 339f2fc65..7efba8f10 100644 --- a/src/Template/Users/change_password.ctp +++ b/src/Template/Users/change_password.ctp @@ -2,26 +2,26 @@ Flash->render('auth') ?> Form->create($user) ?>
- + Form->control('current_password', [ 'type' => 'password', 'required' => true, - 'label' => __d('CakeDC/Users', 'Current password')]); + 'label' => __d('cake_d_c/users', 'Current password')]); ?> Form->control('password', [ 'type' => 'password', 'required' => true, - 'label' => __d('CakeDC/Users', 'New password')]); + 'label' => __d('cake_d_c/users', 'New password')]); ?> Form->control('password_confirm', [ 'type' => 'password', 'required' => true, - 'label' => __d('CakeDC/Users', 'Confirm password')]); + 'label' => __d('cake_d_c/users', 'Confirm password')]); ?>
- Form->button(__d('CakeDC/Users', 'Submit')); ?> + Form->button(__d('cake_d_c/users', 'Submit')); ?> Form->end() ?> \ No newline at end of file diff --git a/src/Template/Users/edit.ctp b/src/Template/Users/edit.ctp index cf0f0504b..f82bbcde6 100644 --- a/src/Template/Users/edit.ctp +++ b/src/Template/Users/edit.ctp @@ -14,54 +14,54 @@ use Cake\Core\Configure; $Users = ${$tableAlias}; ?>
-

+

  • Form->postLink( - __d('CakeDC/Users', 'Delete'), + __d('cake_d_c/users', 'Delete'), ['action' => 'delete', $Users->id], - ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $Users->id)] + ['confirm' => __d('cake_d_c/users', 'Are you sure you want to delete # {0}?', $Users->id)] ); ?>
  • -
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • +
  • Html->link(__d('cake_d_c/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('username', ['label' => __d('cake_d_c/users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('cake_d_c/users', 'Email')]); + echo $this->Form->control('first_name', ['label' => __d('cake_d_c/users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('cake_d_c/users', 'Last name')]); + echo $this->Form->control('token', ['label' => __d('cake_d_c/users', 'Token')]); echo $this->Form->control('token_expires', [ - 'label' => __d('CakeDC/Users', 'Token expires') + 'label' => __d('cake_d_c/users', 'Token expires') ]); echo $this->Form->control('api_token', [ - 'label' => __d('CakeDC/Users', 'API token') + 'label' => __d('cake_d_c/users', 'API token') ]); echo $this->Form->control('activation_date', [ - 'label' => __d('CakeDC/Users', 'Activation date') + 'label' => __d('cake_d_c/users', 'Activation date') ]); echo $this->Form->control('tos_date', [ - 'label' => __d('CakeDC/Users', 'TOS date') + 'label' => __d('cake_d_c/users', 'TOS date') ]); echo $this->Form->control('active', [ - 'label' => __d('CakeDC/Users', 'Active') + 'label' => __d('cake_d_c/users', 'Active') ]); ?>
- Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->button(__d('cake_d_c/users', 'Submit')) ?> Form->end() ?>
Reset Google Authenticator Form->postLink( - __d('CakeDC/Users', 'Reset Google Authenticator Token'), [ + __d('cake_d_c/users', 'Reset Google Authenticator Token'), [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetOneTimePasswordAuthenticator', $Users->id diff --git a/src/Template/Users/index.ctp b/src/Template/Users/index.ctp index c48830bf6..a39a61f66 100644 --- a/src/Template/Users/index.ctp +++ b/src/Template/Users/index.ctp @@ -10,20 +10,20 @@ */ ?>
-

+

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

Paginator->counter() ?>

diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp index a1b0b0b5e..2c1092dc0 100644 --- a/src/Template/Users/login.ctp +++ b/src/Template/Users/login.ctp @@ -16,9 +16,9 @@ use Cake\Core\Configure; 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]) ?> + + Form->control('username', ['label' => __d('cake_d_c/users', 'Username'), 'required' => true]) ?> + Form->control('password', ['label' => __d('cake_d_c/users', 'Password'), 'required' => true]) ?> User->addReCaptcha(); @@ -26,7 +26,7 @@ use Cake\Core\Configure; if (Configure::read('Users.RememberMe.active')) { echo $this->Form->control(Configure::read('Users.Key.Data.rememberMe'), [ 'type' => 'checkbox', - 'label' => __d('CakeDC/Users', 'Remember me'), + 'label' => __d('cake_d_c/users', 'Remember me'), 'checked' => Configure::read('Users.RememberMe.checked') ]); } @@ -34,17 +34,17 @@ use Cake\Core\Configure; Html->link(__d('CakeDC/Users', 'Register'), ['action' => 'register']); + echo $this->Html->link(__d('cake_d_c/users', 'Register'), ['action' => 'register']); } if (Configure::read('Users.Email.required')) { if ($registrationActive) { echo ' | '; } - echo $this->Html->link(__d('CakeDC/Users', 'Reset Password'), ['action' => 'requestResetPassword']); + echo $this->Html->link(__d('cake_d_c/users', 'Reset Password'), ['action' => 'requestResetPassword']); } ?>
User->socialLoginList()); ?> - Form->button(__d('CakeDC/Users', 'Login')); ?> + Form->button(__d('cake_d_c/users', 'Login')); ?> Form->end() ?>
diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp index a53e90732..5450218d5 100644 --- a/src/Template/Users/profile.ctp +++ b/src/Template/Users/profile.ctp @@ -18,37 +18,37 @@ Html->tag( 'span', - __d('CakeDC/Users', '{0} {1}', $user->first_name, $user->last_name), + __d('cake_d_c/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']); ?> + Html->link(__d('cake_d_c/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) + $linkText = empty($escapedUsername) ? __d('cake_d_c/users', 'Link to {0}', h($socialAccount->provider)) : h($socialAccount->username) ?> + ) : '-' ?> Date: Wed, 24 Jul 2019 12:19:45 -0300 Subject: [PATCH 391/685] Don't show social account link when it is empty or "#" --- src/Template/Users/profile.ctp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp index 8b59d9ee2..811ce0121 100644 --- a/src/Template/Users/profile.ctp +++ b/src/Template/Users/profile.ctp @@ -59,11 +59,11 @@ + ) : '-' ?> Date: Wed, 24 Jul 2019 16:43:59 -0300 Subject: [PATCH 392/685] At social login, update social_accounts if exists --- src/Model/Behavior/SocialBehavior.php | 53 +++++++++++++------ tests/Fixture/SocialAccountsFixture.php | 1 + .../Model/Behavior/SocialBehaviorTest.php | 39 +++++++++++++- 3 files changed, 74 insertions(+), 19 deletions(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index a58ec79cb..efc0dafad 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -84,6 +84,10 @@ public function socialLogin(array $data, array $options) } } else { $user = $existingAccount->user; + $accountData = $this->extractAccountData($data); + $this->_table->SocialAccounts->patchEntity($existingAccount, $accountData); + $this->_table->SocialAccounts->save($existingAccount); + } if (!empty($existingAccount)) { if (!$existingAccount->active) { @@ -153,23 +157,7 @@ protected function _createSocialUser($data, $options = []) */ 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 = $this->extractAccountData($data); $accountData['active'] = true; $dataValidated = Hash::get($data, 'validated'); @@ -271,4 +259,35 @@ public function findExistingForSocialLogin(\Cake\ORM\Query $query, array $option $this->_table->aliasField('email') => $options['email'] ]); } + + /** + * Extract the account data to insert/update + * + * @param array $data Social data. + * + * @throws \Exception + */ + protected function extractAccountData(array $data) + { + $accountData = []; + $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')); + + return $accountData; + } } diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php index 48a966eda..b640fe55a 100644 --- a/tests/Fixture/SocialAccountsFixture.php +++ b/tests/Fixture/SocialAccountsFixture.php @@ -34,6 +34,7 @@ class SocialAccountsFixture extends TestFixture '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], + 'link' => ['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], diff --git a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php index 8b96c4b64..c179f4d1c 100644 --- a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php @@ -197,7 +197,7 @@ public function providerFacebookSocialLogin() * * @dataProvider providerFacebookSocialLoginExistingReference */ - public function testSocialLoginExistingReference($data, $options) + public function testSocialLoginExistingReferenceOkay($data, $options) { $this->Behavior->expects($this->never()) ->method('generateUniqueUsername'); @@ -208,9 +208,44 @@ public function testSocialLoginExistingReference($data, $options) $this->Behavior->expects($this->never()) ->method('_updateActive'); - $result = $this->Behavior->socialLogin($data, $options); + $fullData = $data + [ + 'credentials' => [ + 'token' => 'aT0ken' . time(), + 'secret' => 'AS3crEt' . time(), + 'expires' => 1458423682 + ], + 'avatar' => 'http://localhost/avatar.jpg' . time(), + 'link' => 'facebook-link' . time(), + 'bio' => 'This is a sample bio' . time(), + 'raw' => [ + 'bio' => 'This is a raw bio', + 'extra' => 'value', + 'foo' => 'bar', + ] + ]; + $accountBefore = $this->Table->SocialAccounts->find()->where([ + 'SocialAccounts.reference' => $data['id'], + 'SocialAccounts.provider' => $data['provider'] + ])->firstOrFail(); + $result = $this->Behavior->socialLogin($fullData + [], $options); $this->assertEquals($result->id, '00000000-0000-0000-0000-000000000002'); $this->assertTrue($result->active); + + $account = $this->Table->SocialAccounts->find()->where([ + 'SocialAccounts.reference' => $data['id'], + 'SocialAccounts.provider' => $data['provider'] + ])->firstOrFail(); + + $this->assertEquals($fullData['avatar'], $account->avatar); + $this->assertEquals($fullData['link'], $account->link); + $this->assertEquals($fullData['bio'], $account->description); + $this->assertEquals($fullData['raw'], unserialize($account->data)); + $this->assertEquals($fullData['credentials']['token'], $account->token); + $this->assertEquals($fullData['credentials']['secret'], $account->token_secret); + $this->assertNotEmpty($account->token_expires); + $this->assertNotEquals($accountBefore->token_expires, $account->token_expires); + $this->assertSame($accountBefore->id, $account->id); + $this->assertSame($accountBefore->active, $account->active); } /** From a76f40b99e8d7e9a6a1e3d4f586f2524fd82fd42 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 24 Jul 2019 16:57:47 -0300 Subject: [PATCH 393/685] Postgresql and mysql services --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e71ec741f..9fdf9b436 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: php - +services: + - postgresql + - mysql php: - 5.6 - 7.0 @@ -10,7 +12,7 @@ sudo: false env: matrix: - - DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' + - DB=mysql db_dsn='mysql://travis@127.0.0.1/cakephp_test' - DB=pgsql db_dsn='postgres://postgres@127.0.0.1/cakephp_test' - DB=sqlite db_dsn='sqlite:///:memory:' From 47e67f58cdfb827feb3ebf8c48d7a1b6852e86e5 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 24 Jul 2019 17:06:50 -0300 Subject: [PATCH 394/685] phpscs fix --- src/Model/Behavior/SocialBehavior.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index efc0dafad..204ad7e79 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -87,7 +87,6 @@ public function socialLogin(array $data, array $options) $accountData = $this->extractAccountData($data); $this->_table->SocialAccounts->patchEntity($existingAccount, $accountData); $this->_table->SocialAccounts->save($existingAccount); - } if (!empty($existingAccount)) { if (!$existingAccount->active) { From ea7558efd6bf137179045dd9d3476f07d9a01185 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 24 Jul 2019 17:10:53 -0300 Subject: [PATCH 395/685] Urls for reset password and validation should not have prefix --- src/Template/Email/html/reset_password.ctp | 1 + src/Template/Email/html/social_account_validation.ctp | 1 + src/Template/Email/html/validation.ctp | 1 + src/Template/Email/text/reset_password.ctp | 1 + src/Template/Email/text/social_account_validation.ctp | 1 + src/Template/Email/text/validation.ctp | 1 + 6 files changed, 6 insertions(+) diff --git a/src/Template/Email/html/reset_password.ctp b/src/Template/Email/html/reset_password.ctp index f6055a1d4..5af0bb1be 100644 --- a/src/Template/Email/html/reset_password.ctp +++ b/src/Template/Email/html/reset_password.ctp @@ -11,6 +11,7 @@ $activationUrl = [ '_full' => true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetPassword', diff --git a/src/Template/Email/html/social_account_validation.ctp b/src/Template/Email/html/social_account_validation.ctp index acef3fbc5..9df8e84bf 100644 --- a/src/Template/Email/html/social_account_validation.ctp +++ b/src/Template/Email/html/social_account_validation.ctp @@ -18,6 +18,7 @@ $text = __d('CakeDC/Users', 'Activate your social login here'); $activationUrl = [ '_full' => true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'validateAccount', diff --git a/src/Template/Email/html/validation.ctp b/src/Template/Email/html/validation.ctp index 8a1840468..d0909a840 100644 --- a/src/Template/Email/html/validation.ctp +++ b/src/Template/Email/html/validation.ctp @@ -11,6 +11,7 @@ $activationUrl = [ '_full' => true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', diff --git a/src/Template/Email/text/reset_password.ctp b/src/Template/Email/text/reset_password.ctp index 96f001565..e4c8493be 100644 --- a/src/Template/Email/text/reset_password.ctp +++ b/src/Template/Email/text/reset_password.ctp @@ -11,6 +11,7 @@ $activationUrl = [ '_full' => true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetPassword', diff --git a/src/Template/Email/text/social_account_validation.ctp b/src/Template/Email/text/social_account_validation.ctp index 87e2d6813..5a5f4636e 100644 --- a/src/Template/Email/text/social_account_validation.ctp +++ b/src/Template/Email/text/social_account_validation.ctp @@ -11,6 +11,7 @@ $activationUrl = [ '_full' => true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'validateAccount', diff --git a/src/Template/Email/text/validation.ctp b/src/Template/Email/text/validation.ctp index ecf9d96a8..cd5937799 100644 --- a/src/Template/Email/text/validation.ctp +++ b/src/Template/Email/text/validation.ctp @@ -11,6 +11,7 @@ $activationUrl = [ '_full' => true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', From 8f348718b5d696a5cc253f6e893fe73acf44f88d Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 24 Jul 2019 17:13:54 -0300 Subject: [PATCH 396/685] Profile url should not have prefix --- config/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index d5038d5f9..84699d3b4 100644 --- a/config/users.php +++ b/config/users.php @@ -80,7 +80,7 @@ 'Profile' => [ // Allow view other users profiles 'viewOthers' => true, - 'route' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], + 'route' => ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], ], 'Key' => [ 'Session' => [ From 43c281f662be7662a7610320bd8602524172e72c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 24 Jul 2019 17:58:40 -0300 Subject: [PATCH 397/685] Making sure current_password is accessible to patch, so it can be validated. --- src/Controller/Traits/PasswordManagementTrait.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index fd5469eff..2994c8e07 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -65,7 +65,14 @@ public function changePassword() $user = $this->getUsersTable()->patchEntity( $user, $this->request->getData(), - ['validate' => $validator] + [ + 'validate' => $validator, + 'accessibleFields' => [ + 'current_password' => true, + 'password' => true, + 'password_confirm' => true, + ] + ] ); if ($user->getErrors()) { $this->Flash->error(__d('CakeDC/Users', 'Password could not be changed')); From b94f29e7d71cd8881d923af7acab785236fe6401 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 25 Jul 2019 12:43:34 -0300 Subject: [PATCH 398/685] phpunit fix --- .../TestCase/Controller/Traits/PasswordManagementTraitTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index bf1a2faae..02e20bc64 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -61,7 +61,7 @@ public function testChangePasswordHappy() ])); $this->Trait->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); + ->with(['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); $this->Trait->Flash->expects($this->any()) ->method('success') ->with('Password has been changed successfully'); From 1acc29bcdcb07e3e9c5828565f03aec66ff1b4f0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 25 Jul 2019 13:06:54 -0300 Subject: [PATCH 399/685] phpunit fxi --- .../TestCase/Controller/Traits/PasswordManagementTraitTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index bf1a2faae..02e20bc64 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -61,7 +61,7 @@ public function testChangePasswordHappy() ])); $this->Trait->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); + ->with(['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); $this->Trait->Flash->expects($this->any()) ->method('success') ->with('Password has been changed successfully'); From f7cf62216734aa7353c22b86e7ebbff5e81c0e49 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 31 Jul 2019 17:04:21 -0300 Subject: [PATCH 400/685] Don't load routes in bootstrap this block app routes --- config/bootstrap.php | 10 ---------- config/routes.php | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index 042bc020e..5c40ae9c1 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -26,13 +26,3 @@ if (Configure::check('Auth.authenticate') || Configure::check('Auth.authorize')) { trigger_error("Users plugin configurations keys Auth.authenticate and Auth.authorize were removed, please check migration guide https://github.com/CakeDC/users/blob/master/Docs/Documentation/MigrationGuide.md'"); } -$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/routes.php b/config/routes.php index 83663ea1d..c7bb9e4ac 100644 --- a/config/routes.php +++ b/config/routes.php @@ -45,3 +45,13 @@ 'action' => 'callbackLinkSocial', 'plugin' => 'CakeDC/Users', ]); +$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')))] + ); + }); +} From 12bb1674adf7da5197105c8d5e61200a135e7b66 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 31 Jul 2019 17:10:15 -0300 Subject: [PATCH 401/685] Set routes using $routes provided instead of using static methods --- config/routes.php | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/config/routes.php b/config/routes.php index c7bb9e4ac..930896b48 100644 --- a/config/routes.php +++ b/config/routes.php @@ -8,46 +8,47 @@ * @copyright Copyright 2010 - 2018, Cake Development Corporation (https://www.cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +/** + * @var \Cake\Routing\RouteBuilder $routes + */ use Cake\Core\Configure; use Cake\Routing\RouteBuilder; -use Cake\Routing\Router; - -Router::plugin('CakeDC/Users', ['path' => '/users'], function (RouteBuilder $routes) { +$routes->plugin('CakeDC/Users', ['path' => '/users'], function (RouteBuilder $routes) { $routes->fallbacks('DashedRoute'); }); -Router::connect('/accounts/validate/*', [ +$routes->connect('/accounts/validate/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'validate' ]); // Google Authenticator related routes if (Configure::read('OneTimePasswordAuthenticator.login')) { - Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']); + $routes->connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']); - Router::connect('/resetOneTimePasswordAuthenticator', [ + $routes->connect('/resetOneTimePasswordAuthenticator', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetOneTimePasswordAuthenticator' ]); } -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/*', [ +$routes->connect('/profile/*', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile']); +$routes->connect('/login', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); +$routes->connect('/logout', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout']); +$routes->connect('/link-social/*', [ 'controller' => 'Users', 'action' => 'linkSocial', 'plugin' => 'CakeDC/Users', ]); -Router::connect('/callback-link-social/*', [ +$routes->connect('/callback-link-social/*', [ 'controller' => 'Users', 'action' => 'callbackLinkSocial', 'plugin' => 'CakeDC/Users', ]); $oauthPath = Configure::read('OAuth.path'); if (is_array($oauthPath)) { - Router::scope('/auth', function ($routes) use ($oauthPath) { + $routes->scope('/auth', function (RouteBuilder $routes) use ($oauthPath) { $routes->connect( '/:provider', $oauthPath, From e8a4d66d7ee10189d0dcb32a07d8464fdd3ebcd2 Mon Sep 17 00:00:00 2001 From: Jan Holthusen Date: Thu, 1 Aug 2019 10:02:50 +0200 Subject: [PATCH 402/685] Added changed load method for CakePHP 3.8 --- Docs/Documentation/Installation.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index bd8a34803..45228d872 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -55,6 +55,25 @@ Ensure the Users Plugin is loaded in your config/bootstrap.php file Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); ``` +In CakePHP 3.8 , this method is deprecated, load the plugin in /src/Application.php : + +``` +// In src/Application.php. Requires at least 3.6.0 +use Cake\Http\BaseApplication; +use ContactManager\Plugin as ContactManagerPlugin; + +class Application extends BaseApplication { + public function bootstrap() + { + parent::bootstrap(); + + // Load a plugin with a vendor namespace by 'short name' + $this->addPlugin('CakeDC/Users'); + } +} +``` + + Creating Required Tables ------------------------ If you want to use the Users tables to store your users and social accounts: From a09e19d437944fa0aa027b44ef43182f1a0a5776 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 13 Aug 2019 17:11:01 -0300 Subject: [PATCH 403/685] Update Installation.md --- Docs/Documentation/Installation.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 45228d872..e0297b3bd 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -60,15 +60,16 @@ In CakePHP 3.8 , this method is deprecated, load the plugin in /src/Application. ``` // In src/Application.php. Requires at least 3.6.0 use Cake\Http\BaseApplication; -use ContactManager\Plugin as ContactManagerPlugin; -class Application extends BaseApplication { +class Application extends BaseApplication +{ public function bootstrap() { parent::bootstrap(); // Load a plugin with a vendor namespace by 'short name' $this->addPlugin('CakeDC/Users'); + Configure::write('Users.config', ['users']); } } ``` From e220821504c06c981439a99e33347c0b921bb38e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 13 Aug 2019 17:12:12 -0300 Subject: [PATCH 404/685] Update Installation.md --- Docs/Documentation/Installation.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index e0297b3bd..a30f34635 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -59,6 +59,7 @@ In CakePHP 3.8 , this method is deprecated, load the plugin in /src/Application. ``` // In src/Application.php. Requires at least 3.6.0 +namespace App; use Cake\Http\BaseApplication; class Application extends BaseApplication From 5fa8fd33e53f37056a70a8ae31a92360930a0f2f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 27 Aug 2019 15:30:07 -0300 Subject: [PATCH 405/685] Release info for 8.5.0 --- .semver | 2 +- CHANGELOG.md | 5 +++++ README.md | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.semver b/.semver index 90905caf5..56de8e7eb 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 8 -:minor: 4 +:minor: 5 :patch: 0 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e674dde5..739761673 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ Changelog Releases for CakePHP 3 ------------- +* 8.5.0 + * Added new `UsersAuthComponent::EVENT_BEFORE_SOCIAL_LOGIN_REDIRECT` + * Added finder to get existing social account + * Improved social login to updated social account when account already exists + * Improved URLs in template to avoid issue in prefixed routes * 8.4.0 * Rehash password if needed at login diff --git a/README.md b/README.md index ebe742d19..50547f552 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| 3.7 | [master](https://github.com/cakedc/users/tree/master) | 8.4.0 | stable | +| 3.7 | [master](https://github.com/cakedc/users/tree/master) | 8.5.0 | stable | | 3.7 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | -| ^3.7 | [8.4](https://github.com/cakedc/users/tree/8.next) | 8.4.0 | stable | +| ^3.7 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.0 | stable | | 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | | 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | | 3.4 | [5.x](https://github.com/cakedc/users/tree/5.x) | 5.2.0 | stable | From b5fe2033e87df7f278d2d80a5a5c612193c53cc1 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Sun, 22 Sep 2019 21:21:39 +0300 Subject: [PATCH 406/685] add check to plugin initialization --- config/bootstrap.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index 606b5f220..a167a942b 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -21,9 +21,12 @@ collection((array)Configure::read('Users.config'))->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 (!TableRegistry::getTableLocator()->exists('Users')) { + TableRegistry::getTableLocator()->setConfig('Users', ['className' => Configure::read('Users.table')]); +} +if (!TableRegistry::getTableLocator()->exists('CakeDC/Users.Users')) { + 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')); From b8c502b9ec066cc506d335567c4058dff6b84819 Mon Sep 17 00:00:00 2001 From: Daniel Upshaw Date: Thu, 26 Sep 2019 11:44:06 -0400 Subject: [PATCH 407/685] Unlock login action due to session renew after login Per discussion here: https://github.com/cakephp/authentication/issues/284 Since the session needs to be renewed upon login, the `SecurityComponent` becomes incompatible with login forms in particular. We still have CSRF protection, are already checking for specific form fields, and are not writing to the database for the login process -- only reading. Unlocking the login action prevents a `Bad Request` error coming from `SecurityComponent` --- src/Controller/UsersController.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 0040bd2d8..793cb12b4 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -52,7 +52,13 @@ public function initialize() if ($this->components()->has('Security')) { $this->Security->setConfig( 'unlockedActions', - ['u2fRegister', 'u2fRegisterFinish', 'u2fAuthenticate', 'u2fAuthenticateFinish'] + [ + 'login', + 'u2fRegister', + 'u2fRegisterFinish', + 'u2fAuthenticate', + 'u2fAuthenticateFinish' + ] ); } } From 579fadbce48156531e3ec80ae5df4e3858d233d7 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 26 Sep 2019 15:35:00 -0400 Subject: [PATCH 408/685] Code sniffer tests passing --- src/Controller/Traits/U2fTrait.php | 1 + src/Shell/UsersShell.php | 1 + src/View/Helper/UserHelper.php | 1 + tests/TestCase/Authenticator/SocialAuthenticatorTest.php | 1 + tests/TestCase/Controller/Component/SetupComponentTest.php | 1 + tests/TestCase/Controller/Traits/LoginTraitTest.php | 1 + tests/TestCase/Controller/Traits/U2fTraitTest.php | 3 +++ tests/TestCase/PluginTest.php | 1 + tests/TestCase/View/Helper/UserHelperTest.php | 1 + 9 files changed, 11 insertions(+) diff --git a/src/Controller/Traits/U2fTrait.php b/src/Controller/Traits/U2fTrait.php index 56215dd03..0109973cb 100644 --- a/src/Controller/Traits/U2fTrait.php +++ b/src/Controller/Traits/U2fTrait.php @@ -41,6 +41,7 @@ public function redirectWithQuery($url) return $this->redirect($url); } + /** * U2f entry point * diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 27d6cf8ae..a4214443b 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -399,6 +399,7 @@ 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/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 4e7618d05..853cd0fb5 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -199,6 +199,7 @@ public function isAuthorized($url = null) return $this->AuthLink->isAuthorized($url); } + /** * Create links for all social providers enabled social link (connect) * diff --git a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php index e074c5a66..5f49a3970 100644 --- a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php @@ -506,6 +506,7 @@ public function dataProviderAuthenticateErrorException() ] ]; } + /** * Test authenticate method with successfull authentication * diff --git a/tests/TestCase/Controller/Component/SetupComponentTest.php b/tests/TestCase/Controller/Component/SetupComponentTest.php index 2846b447b..ea5b5cc6f 100644 --- a/tests/TestCase/Controller/Component/SetupComponentTest.php +++ b/tests/TestCase/Controller/Component/SetupComponentTest.php @@ -74,6 +74,7 @@ public function dataProviderInitialization() [false, false, false] ]; } + /** * Test initial setup * diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 0952d79e3..432f87996 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -365,6 +365,7 @@ public function dataProviderLogin() ] ]; } + /** * test socialLogin/login failure * diff --git a/tests/TestCase/Controller/Traits/U2fTraitTest.php b/tests/TestCase/Controller/Traits/U2fTraitTest.php index 933b8455a..f6ce21baf 100644 --- a/tests/TestCase/Controller/Traits/U2fTraitTest.php +++ b/tests/TestCase/Controller/Traits/U2fTraitTest.php @@ -36,6 +36,7 @@ class U2fTraitTest extends BaseTraitTest public $fixtures = [ 'plugin.CakeDC/Users.Users', ]; + /** * setup * @@ -101,6 +102,7 @@ public function dataProviderU2User() [$withRegistration, ['action' => 'u2fAuthenticate']] ]; } + /** * Test u2f method * @@ -467,6 +469,7 @@ public function dataProviderU2fAuthenticateRedirectCustomUser() [$withWhoutRegistration, ['action' => 'u2fRegister']], ]; } + /** * Test u2fAuthenticate method redirect cases * diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index b8da69ee3..4320c9e3b 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -205,6 +205,7 @@ public function testGetAuthenticationServiceCallableDefined() $actualService = $plugin->getAuthenticationService($request, $response); $this->assertSame($service, $actualService); } + /** * testGetAuthenticationService * diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 1c2056e56..0163eb39a 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -46,6 +46,7 @@ class UserHelperTest extends TestCase * @var \CakeDC\Users\View\Helper\AuthLinkHelper */ private $AuthLink; + /** * setUp method * From 9fec4a1a5387a35faa80d854763e2453aa8c6975 Mon Sep 17 00:00:00 2001 From: "Jeffrey L. Roberts" Date: Sun, 29 Sep 2019 21:16:37 -0400 Subject: [PATCH 409/685] Added command to create Super User --- Docs/Documentation/Installation.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index a30f34635..53f3d1b32 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -88,6 +88,12 @@ Note you don't need to use the provided tables, you could customize the table na 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 +You can create the first user, the super user by issuing the following command + +``` +bin/cake users addSuperuser +``` + Customization ---------- From 55c58ca1283df37860fb4696aa6f1323c593aa6d Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 Oct 2019 12:22:36 -0300 Subject: [PATCH 410/685] phpcs fixes --- src/Auth/Social/Mapper/AbstractMapper.php | 1 + src/Controller/Traits/U2fTrait.php | 1 + src/Shell/UsersShell.php | 1 + src/View/Helper/UserHelper.php | 1 + .../TestCase/Controller/Component/RememberMeComponentTest.php | 1 + tests/TestCase/Controller/Component/UsersAuthComponentTest.php | 1 + tests/TestCase/Controller/Traits/U2fTraitTest.php | 3 +++ 7 files changed, 9 insertions(+) diff --git a/src/Auth/Social/Mapper/AbstractMapper.php b/src/Auth/Social/Mapper/AbstractMapper.php index 1d7971ab2..8a0b2a79c 100644 --- a/src/Auth/Social/Mapper/AbstractMapper.php +++ b/src/Auth/Social/Mapper/AbstractMapper.php @@ -65,6 +65,7 @@ public function __construct($rawData, $mapFields = null) } $this->_mapFields = array_merge($this->_defaultMapFields, $this->_mapFields); } + /** * Invoke method * diff --git a/src/Controller/Traits/U2fTrait.php b/src/Controller/Traits/U2fTrait.php index 30d581a83..e9c534100 100644 --- a/src/Controller/Traits/U2fTrait.php +++ b/src/Controller/Traits/U2fTrait.php @@ -37,6 +37,7 @@ public function redirectWithQuery($url) return $this->redirect($url); } + /** * U2f entry point * diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 292dc71b3..45f1346c9 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -399,6 +399,7 @@ 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/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 348239e19..a4eec7614 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -188,6 +188,7 @@ public function isAuthorized($url = null) return $this->AuthLink->isAuthorized($url); } + /** * Create links for all social providers enabled social link (connect) * diff --git a/tests/TestCase/Controller/Component/RememberMeComponentTest.php b/tests/TestCase/Controller/Component/RememberMeComponentTest.php index 87607965b..a018051dd 100644 --- a/tests/TestCase/Controller/Component/RememberMeComponentTest.php +++ b/tests/TestCase/Controller/Component/RememberMeComponentTest.php @@ -28,6 +28,7 @@ class RememberMeComponentTest extends TestCase public $fixtures = [ 'plugin.CakeDC/Users.Users' ]; + /** * setUp method * diff --git a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php index 739f033b4..5f026717e 100644 --- a/tests/TestCase/Controller/Component/UsersAuthComponentTest.php +++ b/tests/TestCase/Controller/Component/UsersAuthComponentTest.php @@ -480,6 +480,7 @@ public function testIsUrlAuthorizedBaseUrl() $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 diff --git a/tests/TestCase/Controller/Traits/U2fTraitTest.php b/tests/TestCase/Controller/Traits/U2fTraitTest.php index 9af35c4e8..3d549bfe2 100644 --- a/tests/TestCase/Controller/Traits/U2fTraitTest.php +++ b/tests/TestCase/Controller/Traits/U2fTraitTest.php @@ -35,6 +35,7 @@ class U2fTraitTest extends BaseTraitTest public $fixtures = [ 'plugin.CakeDC/Users.Users', ]; + /** * setup * @@ -104,6 +105,7 @@ public function dataProviderU2User() [$withRegistration, ['action' => 'u2fAuthenticate']] ]; } + /** * Test u2f method * @@ -451,6 +453,7 @@ public function dataProviderU2fAuthenticateRedirectCustomUser() [$withWhoutRegistration, ['action' => 'u2fRegister']], ]; } + /** * Test u2fAuthenticate method redirect cases * From 8d941f40169af313a44dc9cc42690cf0c24e1a06 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 Oct 2019 12:31:52 -0300 Subject: [PATCH 411/685] #826 logout url should not have 'prefix' --- src/View/Helper/UserHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index a4eec7614..e7361ff57 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -98,7 +98,7 @@ public function socialLoginList(array $providerOptions = []) public function logout($message = null, $options = []) { return $this->AuthLink->link(empty($message) ? __d('CakeDC/Users', 'Logout') : $message, [ - 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout', + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout', ], $options); } From 315fe7d4b6894686a7796bb2e79fab404c7cac19 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 Oct 2019 12:38:48 -0300 Subject: [PATCH 412/685] #825 socialEmai action should not have 'prefix' --- src/Controller/Traits/LoginTrait.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Controller/Traits/LoginTrait.php b/src/Controller/Traits/LoginTrait.php index cd8cb5893..adb69361b 100644 --- a/src/Controller/Traits/LoginTrait.php +++ b/src/Controller/Traits/LoginTrait.php @@ -113,6 +113,7 @@ public function failedSocialLogin($exception, $data, $flash = false) $this->request->getSession()->write(Configure::read('Users.Key.Session.social'), $data); return $this->redirect([ + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail' From 30f1fef9f379698067712909af3fcada08c1d1e1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 5 Oct 2019 12:46:50 -0300 Subject: [PATCH 413/685] #825 socialEmai action should not have 'prefix' --- tests/TestCase/Controller/Traits/LoginTraitTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 33e92281b..abfa187db 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -356,7 +356,7 @@ public function testFailedSocialLoginMissingEmail() $this->Trait->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); + ->with(['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail']); $this->Trait->failedSocialLogin($event->data['exception'], $event->data['rawData'], true); } From 7e2c668017c90840e0ee17eb70db8ef8480e5d69 Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Mon, 7 Oct 2019 19:02:03 +0200 Subject: [PATCH 414/685] Add event if existing account --- src/Controller/Component/UsersAuthComponent.php | 1 + src/Model/Behavior/SocialBehavior.php | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/Controller/Component/UsersAuthComponent.php b/src/Controller/Component/UsersAuthComponent.php index c190f7b1f..5effa44a5 100644 --- a/src/Controller/Component/UsersAuthComponent.php +++ b/src/Controller/Component/UsersAuthComponent.php @@ -35,6 +35,7 @@ class UsersAuthComponent extends Component const EVENT_AFTER_LOGOUT = 'Users.Component.UsersAuth.afterLogout'; const EVENT_BEFORE_SOCIAL_LOGIN_REDIRECT = 'Users.Component.UsersAuth.beforeSocialLoginRedirect'; const EVENT_BEFORE_SOCIAL_LOGIN_USER_CREATE = 'Users.Component.UsersAuth.beforeSocialLoginUserCreate'; + const EVENT_SOCIAL_LOGIN_EXISTING_ACCOUNT = 'Users.Component.UsersAuth.socialLoginExistingAccount'; const EVENT_AFTER_CHANGE_PASSWORD = 'Users.Component.UsersAuth.afterResetPassword'; const EVENT_ON_EXPIRED_TOKEN = 'Users.Component.UsersAuth.onExpiredToken'; const EVENT_AFTER_RESEND_TOKEN_VALIDATION = 'Users.Component.UsersAuth.afterResendTokenValidation'; diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 204ad7e79..3fb75cf5a 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -87,6 +87,14 @@ public function socialLogin(array $data, array $options) $accountData = $this->extractAccountData($data); $this->_table->SocialAccounts->patchEntity($existingAccount, $accountData); $this->_table->SocialAccounts->save($existingAccount); + $event = $this->dispatchEvent(UsersAuthComponent::EVENT_SOCIAL_LOGIN_EXISTING_ACCOUNT, [ + 'userEntity' => $user, + 'data' => $data + ]); + + if ($event->result instanceof EntityInterface) { + $user = $this->_table->save($event->result); + } } if (!empty($existingAccount)) { if (!$existingAccount->active) { From 7b22002257e608ef722fa2716725d45bbb989a8f Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Mon, 7 Oct 2019 19:18:31 +0200 Subject: [PATCH 415/685] Release info for 8.5.1 --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index 56de8e7eb..9999d2736 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 8 :minor: 5 -:patch: 0 +:patch: 1 :special: '' From ddcd0752f693ea45c7fac7eb02876e8d69fbedda Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Mon, 7 Oct 2019 19:19:16 +0200 Subject: [PATCH 416/685] Release info for 8.5.1 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 50547f552..7d94e1e43 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| 3.7 | [master](https://github.com/cakedc/users/tree/master) | 8.5.0 | stable | +| 3.7 | [master](https://github.com/cakedc/users/tree/master) | 8.5.1 | stable | | 3.7 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | -| ^3.7 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.0 | stable | +| ^3.7 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | | 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | | 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | | 3.4 | [5.x](https://github.com/cakedc/users/tree/5.x) | 5.2.0 | stable | @@ -73,6 +73,6 @@ This repository follows the [CakeDC Plugin Standard](https://www.cakedc.com/plug License ------- -Copyright 2017 Cake Development Corporation (CakeDC). All rights reserved. +Copyright 2019 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. From 04c543edbec3f6a4860f49f761143a37bb52f6fd Mon Sep 17 00:00:00 2001 From: Alejandro Ibarra Date: Mon, 7 Oct 2019 19:20:24 +0200 Subject: [PATCH 417/685] Release for 8.5.1 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 739761673..de7361321 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Changelog Releases for CakePHP 3 ------------- +* 8.5.1 + * Added new `UsersAuthComponent::EVENT_SOCIAL_LOGIN_EXISTING_ACCOUNT` * 8.5.0 * Added new `UsersAuthComponent::EVENT_BEFORE_SOCIAL_LOGIN_REDIRECT` * Added finder to get existing social account From dbf1302b4a990f799866e02c3b338004890693c6 Mon Sep 17 00:00:00 2001 From: Daniel Upshaw Date: Wed, 9 Oct 2019 15:38:50 -0400 Subject: [PATCH 418/685] Reformatting to re-trigger travis-ci tests --- src/Controller/UsersController.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 793cb12b4..311e47b83 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -52,13 +52,7 @@ public function initialize() if ($this->components()->has('Security')) { $this->Security->setConfig( 'unlockedActions', - [ - 'login', - 'u2fRegister', - 'u2fRegisterFinish', - 'u2fAuthenticate', - 'u2fAuthenticateFinish' - ] + ['login', 'u2fRegister', 'u2fRegisterFinish', 'u2fAuthenticate', 'u2fAuthenticateFinish'] ); } } From 0164b415365cc913fbfe1c83cb4a7e78899a6cef Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 Oct 2019 12:19:02 -0300 Subject: [PATCH 419/685] fixing tests after merge from master --- src/Controller/Traits/PasswordManagementTrait.php | 7 +++---- src/Model/Table/SocialAccountsTable.php | 2 +- src/Model/Table/UsersTable.php | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 63866025a..60d753e3b 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -66,15 +66,14 @@ public function changePassword($id = null) // password reset $user->id = $this->request->getSession()->read(Configure::read('Users.Key.Session.resetPasswordUserId')); $validatePassword = false; - $redirect = $this->Auth->getConfig('loginAction'); + $redirect = $this->Authentication->getConfig('loginAction'); if (!$user->id) { $this->Flash->error(__d('cake_d_c/users', 'User was not found')); - $this->redirect($this->Authentication->getConfig('loginAction')); + $this->redirect($redirect); return; } - //@todo add to the documentation: list of routes used - $redirect = $this->Authentication->getConfig('loginAction'); + } $this->set('validatePassword', $validatePassword); if ($this->request->is(['post', 'put'])) { diff --git a/src/Model/Table/SocialAccountsTable.php b/src/Model/Table/SocialAccountsTable.php index 5abe0f652..4a623b5f6 100644 --- a/src/Model/Table/SocialAccountsTable.php +++ b/src/Model/Table/SocialAccountsTable.php @@ -57,7 +57,7 @@ public function validationDefault(Validator $validator) { $validator ->add('id', 'valid', ['rule' => 'uuid']) - ->allowEmptyString('id', 'create'); + ->allowEmptyString('id', null, 'create'); $validator ->requirePresence('provider', 'create') diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index edfff82f1..d0004280f 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -120,7 +120,7 @@ public function validationCurrentPassword(Validator $validator) public function validationDefault(Validator $validator) { $validator - ->allowEmptyString('id', 'create'); + ->allowEmptyString('id', null, 'create'); $validator ->requirePresence('username', 'create') From 9c4cae3fcb5046eaf3c16a7114819844992cdd4d Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 Oct 2019 12:21:37 -0300 Subject: [PATCH 420/685] php cs fixes --- src/Controller/Traits/LinkSocialTrait.php | 4 ++-- src/Controller/Traits/PasswordManagementTrait.php | 1 - src/Plugin.php | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index b95096fe4..c7b73d1b4 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -13,11 +13,11 @@ use CakeDC\Auth\Social\MapUser; use CakeDC\Auth\Social\Service\ServiceFactory; -use Cake\Utility\Hash; use CakeDC\Users\Plugin; +use Cake\Utility\Hash; /** - * Ações para "linkar" contas sociais + * Actions to allow user to link social accounts * */ trait LinkSocialTrait diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 60d753e3b..22ce6a791 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -73,7 +73,6 @@ public function changePassword($id = null) return; } - } $this->set('validatePassword', $validatePassword); if ($this->request->is(['post', 'put'])) { diff --git a/src/Plugin.php b/src/Plugin.php index 003b610c0..7ffe5b5ab 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -32,6 +32,7 @@ class Plugin extends BasePlugin implements AuthenticationServiceProviderInterfac const EVENT_SOCIAL_LOGIN_EXISTING_ACCOUNT = 'Users.Global.socialLoginExistingAccount'; const EVENT_ON_EXPIRED_TOKEN = 'Users.Global.onExpiredToken'; const EVENT_AFTER_RESEND_TOKEN_VALIDATION = 'Users.Global.afterResendTokenValidation'; + /** * Returns an authentication service instance. * From 54e3eee25e54d472521f7c83831e04e624d44f22 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 Oct 2019 15:13:39 -0300 Subject: [PATCH 421/685] Fix private property usage --- src/Model/Behavior/SocialBehavior.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index a4dcb0bfb..d3062debb 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -14,6 +14,7 @@ namespace CakeDC\Users\Model\Behavior; use Cake\Core\Configure; +use Cake\Datasource\EntityInterface; use Cake\Event\EventDispatcherTrait; use Cake\Utility\Hash; use CakeDC\Users\Exception\AccountNotActiveException; @@ -93,8 +94,8 @@ public function socialLogin(array $data, array $options) 'data' => $data ]); - if ($event->result instanceof EntityInterface) { - $user = $this->_table->save($event->result); + if ($event->getResult() instanceof EntityInterface) { + $user = $this->_table->save($event->getResult()); } } if (!empty($existingAccount)) { From e34e1d23783065efe9bb463f229701e9e83662de Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 Oct 2019 15:18:42 -0300 Subject: [PATCH 422/685] fixing tests --- src/Controller/Traits/PasswordManagementTrait.php | 3 +-- .../TestCase/Controller/Traits/PasswordManagementTraitTest.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 171c3367c..7b090f88b 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -198,8 +198,7 @@ public function resetOneTimePasswordAuthenticator($id = null) $message = __d('cake_d_c/users', 'Google Authenticator token was successfully reset'); $this->Flash->success($message, 'default'); } catch (\Exception $e) { - $message = $e->getMessage(); - $this->Flash->error($message, 'default'); + $this->Flash->error(__d('cake_d_c/users', 'Could not reset Google Authenticator'), 'default'); } } diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 531b54ccd..3a305448a 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -486,7 +486,7 @@ public function ensureOneTimePasswordAuthenticatorResets() { $error = 'error'; $success = 'success'; - $errorMsg = 'You are not allowed to reset users Google Authenticator token'; + $errorMsg = 'Could not reset Google Authenticator'; $successMsg = 'Google Authenticator token was successfully reset'; return [ From 3af406b55027f29e4020ec6c23d8d163a696331e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 Oct 2019 16:01:12 -0300 Subject: [PATCH 423/685] phpcs and fix tests --- .../Traits/OneTimePasswordVerifyTrait.php | 8 +++++-- .../Traits/PasswordManagementTrait.php | 10 +++++--- src/Controller/Traits/RegisterTrait.php | 3 ++- src/Controller/Traits/UserValidationTrait.php | 6 +++-- src/Loader/AuthenticationServiceLoader.php | 5 +++- src/Loader/MiddlewareQueueLoader.php | 5 +++- src/Middleware/SocialAuthMiddleware.php | 10 ++++---- src/Model/Behavior/SocialAccountBehavior.php | 16 +++++++++---- src/Model/Behavior/SocialBehavior.php | 9 ++++--- src/Model/Table/UsersTable.php | 5 +++- src/Plugin.php | 5 ++-- src/Shell/UsersShell.php | 10 ++++++-- src/View/Helper/UserHelper.php | 14 ++++++++--- tests/TestApplication.php | 1 + .../Traits/PasswordManagementTraitTest.php | 1 + ...haTraitTest.php => ReCaptchaTraitTest.php} | 0 .../Traits/UserValidationTraitTest.php | 1 + tests/TestCase/Mailer/UsersMailerTest.php | 24 +++++++++---------- .../Model/Behavior/SocialBehaviorTest.php | 8 +++---- 19 files changed, 94 insertions(+), 47 deletions(-) rename tests/TestCase/Controller/Traits/{RecaptchaTraitTest.php => ReCaptchaTraitTest.php} (100%) diff --git a/src/Controller/Traits/OneTimePasswordVerifyTrait.php b/src/Controller/Traits/OneTimePasswordVerifyTrait.php index 4fba32c7d..ea827aa63 100644 --- a/src/Controller/Traits/OneTimePasswordVerifyTrait.php +++ b/src/Controller/Traits/OneTimePasswordVerifyTrait.php @@ -40,7 +40,9 @@ public function verify() return $this->redirect($loginAction); } - $temporarySession = $this->getRequest()->getSession()->read(AuthenticationService::TWO_FACTOR_VERIFY_SESSION_KEY); + $temporarySession = $this->getRequest()->getSession()->read( + AuthenticationService::TWO_FACTOR_VERIFY_SESSION_KEY + ); $secretVerified = $temporarySession['secret_verified'] ?? null; // showing QR-code until shared secret is verified if (!$secretVerified) { @@ -80,7 +82,9 @@ protected function isVerifyAllowed() return false; } - $temporarySession = $this->getRequest()->getSession()->read(AuthenticationService::TWO_FACTOR_VERIFY_SESSION_KEY); + $temporarySession = $this->getRequest()->getSession()->read( + AuthenticationService::TWO_FACTOR_VERIFY_SESSION_KEY + ); if (empty($temporarySession) || !isset($temporarySession['id'])) { $message = __d('cake_d_c/users', 'Could not find user data'); diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 7b090f88b..1dd7de656 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -58,14 +58,18 @@ public function changePassword($id = null) $validatePassword = true; $redirect = Configure::read('Users.Profile.route'); } else { - $this->Flash->error(__d('CakeDC/Users', 'Changing another user\'s password is not allowed')); + $this->Flash->error( + __d('CakeDC/Users', 'Changing another user\'s password is not allowed') + ); $this->redirect(Configure::read('Users.Profile.route')); return; } } else { // password reset - $user->id = $this->getRequest()->getSession()->read(Configure::read('Users.Key.Session.resetPasswordUserId')); + $user->id = $this->getRequest()->getSession()->read( + Configure::read('Users.Key.Session.resetPasswordUserId') + ); $validatePassword = false; $redirect = $this->Authentication->getConfig('loginAction'); if (!$user->id) { @@ -91,7 +95,7 @@ public function changePassword($id = null) 'current_password' => true, 'password' => true, 'password_confirm' => true, - ] + ], ] ); diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index d4ca90fda..a3ab7ae4f 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -70,7 +70,8 @@ public function register() if ($result instanceof EntityInterface) { $data = $result->toArray(); $data['password'] = $requestData['password']; //since password is a hidden property - if ($userSaved = $usersTable->register($user, $data, $options)) { + $userSaved = $usersTable->register($user, $data, $options); + if ($userSaved) { return $this->_afterRegister($userSaved); } else { $this->set(compact('user')); diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 2919d2291..d746a4eb4 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -94,12 +94,14 @@ public function resendTokenValidation() } $reference = $this->getRequest()->getData('reference'); try { - if ($this->getUsersTable()->resetToken($reference, [ + if ( + $this->getUsersTable()->resetToken($reference, [ 'expiration' => Configure::read('Users.Token.expiration'), 'checkActive' => true, 'sendEmail' => true, 'type' => 'email', - ])) { + ]) + ) { $event = $this->dispatchEvent(Plugin::EVENT_AFTER_RESEND_TOKEN_VALIDATION); $result = $event->getResult(); if (!empty($event) && is_array($result)) { diff --git a/src/Loader/AuthenticationServiceLoader.php b/src/Loader/AuthenticationServiceLoader.php index cc5fa59df..1b99b3726 100644 --- a/src/Loader/AuthenticationServiceLoader.php +++ b/src/Loader/AuthenticationServiceLoader.php @@ -84,7 +84,10 @@ protected function loadAuthenticators($service) */ protected function loadTwoFactorAuthenticator($service) { - if (Configure::read('OneTimePasswordAuthenticator.login') !== false || Configure::read('U2f.enabled') !== false) { + if ( + Configure::read('OneTimePasswordAuthenticator.login') !== false + || Configure::read('U2f.enabled') !== false + ) { $service->loadAuthenticator('CakeDC/Auth.TwoFactor', [ 'skipTwoFactorVerify' => true, ]); diff --git a/src/Loader/MiddlewareQueueLoader.php b/src/Loader/MiddlewareQueueLoader.php index 2f909eb78..09e10ae26 100644 --- a/src/Loader/MiddlewareQueueLoader.php +++ b/src/Loader/MiddlewareQueueLoader.php @@ -92,7 +92,10 @@ protected function loadAuthenticationMiddleware(MiddlewareQueue $middlewareQueue */ protected function load2faMiddleware(MiddlewareQueue $middlewareQueue) { - if (Configure::read('OneTimePasswordAuthenticator.login') !== false || Configure::read('U2f.enabled') !== false) { + if ( + Configure::read('OneTimePasswordAuthenticator.login') !== false + || Configure::read('U2f.enabled') !== false + ) { $middlewareQueue->add(TwoFactorMiddleware::class); } } diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 88652a9fa..f5ad6281d 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -98,7 +98,7 @@ protected function responseWithActionLocation(Response $response, $action) * Go to next handling SocialAuthenticationException * * @param \Cake\Http\ServerRequest $request The request - * @param \Psr\Http\Server\RequestHandlerInterface $handler + * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler. * * @return \Psr\Http\Message\ResponseInterface */ @@ -112,11 +112,11 @@ protected function goNext(ServerRequestInterface $request, RequestHandlerInterfa } /** - * Process an incoming server request. + * Callable implementation for the middleware stack. * - * Processes an incoming server request in order to produce a response. - * If unable to produce the response itself, it may delegate to the provided - * request handler to do so. + * @param \Psr\Http\Message\ServerRequestInterface $request The request. + * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler. + * @return \Psr\Http\Message\ResponseInterface A response. */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index e0438d892..3fff00472 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -58,7 +58,9 @@ public function afterSave(EventInterface $event, EntityInterface $entity, ArrayO if ($entity->get('active')) { return true; } - $user = $this->_table->getAssociation('Users')->find()->where(['Users.id' => $entity->get('user_id'), 'Users.active' => true])->first(); + $user = $this->_table->getAssociation('Users')->find() + ->where(['Users.id' => $entity->get('user_id'), 'Users.active' => true]) + ->first(); if (empty($user)) { return true; } @@ -102,7 +104,9 @@ public function validateAccount($provider, $reference, $token) throw new AccountAlreadyActiveException(__d('cake_d_c/users', "Account already validated")); } } else { - throw new RecordNotFoundException(__d('cake_d_c/users', "Account not found for the given token and email.")); + throw new RecordNotFoundException( + __d('cake_d_c/users', "Account not found for the given token and email.") + ); } return $this->_activateAccount($socialAccount); @@ -126,10 +130,14 @@ public function resendValidation($provider, $reference) if (!empty($socialAccount)) { if ($socialAccount->active) { - throw new AccountAlreadyActiveException(__d('cake_d_c/users', "Account already validated")); + throw new AccountAlreadyActiveException( + __d('cake_d_c/users', "Account already validated") + ); } } else { - throw new RecordNotFoundException(__d('cake_d_c/users', "Account not found for the given token and email.")); + throw new RecordNotFoundException( + __d('cake_d_c/users', "Account not found for the given token and email.") + ); } return $this->sendSocialValidationEmail($socialAccount, $socialAccount->user); diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index d3062debb..37ad1e291 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -82,7 +82,9 @@ public function socialLogin(array $data, array $options) $existingAccount = $user->social_accounts[0]; } else { //@todo: what if we don't have a social account after createSocialUser? - throw new InvalidArgumentException(__d('cake_d_c/users', 'Unable to login user with reference {0}', $reference)); + throw new InvalidArgumentException( + __d('cake_d_c/users', 'Unable to login user with reference {0}', $reference) + ); } } else { $user = $existingAccount->user; @@ -91,7 +93,7 @@ public function socialLogin(array $data, array $options) $this->_table->SocialAccounts->save($existingAccount); $event = $this->dispatchEvent(Plugin::EVENT_SOCIAL_LOGIN_EXISTING_ACCOUNT, [ 'userEntity' => $user, - 'data' => $data + 'data' => $data, ]); if ($event->getResult() instanceof EntityInterface) { @@ -267,7 +269,7 @@ public function generateUniqueUsername($username) public function findExistingForSocialLogin(\Cake\ORM\Query $query, array $options) { return $query->where([ - $this->_table->aliasField('email') => $options['email'] + $this->_table->aliasField('email') => $options['email'], ]); } @@ -277,6 +279,7 @@ public function findExistingForSocialLogin(\Cake\ORM\Query $query, array $option * @param array $data Social data. * * @throws \Exception + * @return array */ protected function extractAccountData(array $data) { diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 627115671..abc1b3698 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -101,7 +101,10 @@ public function validationPasswordConfirm(Validator $validator) ->add('password', [ 'password_confirm_check' => [ 'rule' => ['compareWith', 'password_confirm'], - 'message' => __d('cake_d_c/users', 'Your password does not match your confirm password. Please try again'), + 'message' => __d( + 'cake_d_c/users', + 'Your password does not match your confirm password. Please try again' + ), 'allowEmpty' => false, ]]); diff --git a/src/Plugin.php b/src/Plugin.php index e488ffe55..6b5fc5d91 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -15,6 +15,7 @@ use Authentication\AuthenticationServiceInterface; use Authentication\AuthenticationServiceProviderInterface; +use Authorization\AuthorizationServiceInterface; use Authorization\AuthorizationServiceProviderInterface; use Cake\Core\BasePlugin; use Cake\Core\Configure; @@ -46,7 +47,6 @@ class Plugin extends BasePlugin implements AuthenticationServiceProviderInterfac * Returns an authentication service instance. * * @param \Psr\Http\Message\ServerRequestInterface $request Request - * @param \Psr\Http\Message\ResponseInterface $response Response * @return \Authentication\AuthenticationServiceInterface */ public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface @@ -59,7 +59,7 @@ public function getAuthenticationService(ServerRequestInterface $request): Authe /** * {@inheritdoc} */ - public function getAuthorizationService(ServerRequestInterface $request): \Authorization\AuthorizationServiceInterface + public function getAuthorizationService(ServerRequestInterface $request): AuthorizationServiceInterface { $key = 'Auth.Authorization.serviceLoader'; @@ -80,7 +80,6 @@ public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue * Load a service defined in configuration $loaderKey * * @param \Psr\Http\Message\ServerRequestInterface $request The request. - * @param \Psr\Http\Message\ResponseInterface $loaderKey The response. * @param string $loaderKey service loader key * * @return mixed diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 376fdd5aa..ee2158548 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -241,10 +241,16 @@ public function passwordEmail() 'sendEmail' => true, ]); if ($resetUser) { - $msg = __d('cake_d_c/users', 'Please ask the user to check the email to continue with password reset process'); + $msg = __d( + 'cake_d_c/users', + 'Please ask the user to check the email to continue with password reset process' + ); $this->out($msg); } else { - $msg = __d('cake_d_c/users', 'The password token could not be generated. Please try again'); + $msg = __d( + 'cake_d_c/users', + 'The password token could not be generated. Please try again' + ); $this->abort($msg); } } diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 6e1ce30e6..0617860ff 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -83,7 +83,8 @@ public function socialLoginList(array $providerOptions = []) $outProviders = []; $providers = Configure::read('OAuth.providers'); foreach ($providers as $provider => $options) { - if (!empty($options['options']['redirectUri']) && + if ( + !empty($options['options']['redirectUri']) && !empty($options['options']['clientId']) && !empty($options['options']['clientSecret']) ) { @@ -155,7 +156,13 @@ public function addReCaptchaScript() public function addReCaptcha() { if (!Configure::read('Users.reCaptcha.key')) { - return $this->Html->tag('p', __d('cake_d_c/users', 'reCaptcha is not configured! Please configure Users.reCaptcha.key')); + return $this->Html->tag( + 'p', + __d( + 'cake_d_c/users', + 'reCaptcha is not configured! Please configure Users.reCaptcha.key' + ) + ); } $this->addReCaptchaScript(); $this->Form->unlockField('g-recaptcha-response'); @@ -260,7 +267,8 @@ function ($item) { $providers = Configure::read('OAuth.providers'); foreach ($providers as $name => $provider) { - if (!empty($provider['options']['callbackLinkSocialUri']) && + if ( + !empty($provider['options']['callbackLinkSocialUri']) && !empty($provider['options']['linkSocialUri']) && !empty($provider['options']['clientId']) && !empty($provider['options']['clientSecret']) diff --git a/tests/TestApplication.php b/tests/TestApplication.php index 0a2138c0d..3e925c15f 100644 --- a/tests/TestApplication.php +++ b/tests/TestApplication.php @@ -29,6 +29,7 @@ class TestApplication extends \Cake\Http\BaseApplication * * @return \Cake\Http\MiddlewareQueue */ + /** * Setup the middleware queue your application will use. * diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 3a305448a..9c75ef05b 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -24,6 +24,7 @@ class PasswordManagementTraitTest extends BaseTraitTest * @var \CakeDC\Users\Controller\UsersController */ public $Trait; + /** * setUp * diff --git a/tests/TestCase/Controller/Traits/RecaptchaTraitTest.php b/tests/TestCase/Controller/Traits/ReCaptchaTraitTest.php similarity index 100% rename from tests/TestCase/Controller/Traits/RecaptchaTraitTest.php rename to tests/TestCase/Controller/Traits/ReCaptchaTraitTest.php diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index 5d8d775a7..d34a6a726 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -21,6 +21,7 @@ class UserValidationTraitTest extends BaseTraitTest * @var \CakeDC\Users\Controller\UsersController */ public $Trait; + /** * setup * diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index f98cc6e44..76652511d 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -38,14 +38,14 @@ class UsersMailerTest extends TestCase public function setUp(): void { parent::setUp(); - $this->Email = $this->getMockBuilder('Cake\Mailer\Email') + $this->Email = $this->getMockBuilder('Cake\Mailer\Message') ->setMethods(['setTo', 'setSubject', 'setViewVars', 'setTemplate']) ->getMock(); $this->UsersMailer = $this->getMockBuilder('CakeDC\Users\Mailer\UsersMailer') - ->setConstructorArgs([$this->Email]) - ->setMethods(['setTo', 'setSubject', 'setViewVars', 'setTemplate']) + ->setMethods(['setViewVars']) ->getMock(); + $this->UsersMailer->setMessage($this->Email); } /** @@ -74,7 +74,7 @@ public function testValidation() 'token' => '12345', ]; $user = $table->newEntity($data); - $this->UsersMailer->expects($this->once()) + $this->Email->expects($this->once()) ->method('setTo') ->with($user['email']) ->will($this->returnValue($this->Email)); @@ -84,10 +84,10 @@ public function testValidation() ->with('FirstName, Your account validation link') ->will($this->returnValue($this->Email)); - $this->Email->expects($this->once()) + $this->UsersMailer->expects($this->once()) ->method('setViewVars') ->with($data) - ->will($this->returnValue($this->Email)); + ->will($this->returnValue($this->UsersMailer)); $this->invokeMethod($this->UsersMailer, 'validation', [$user]); } @@ -102,7 +102,7 @@ public function testSocialAccountValidation() $social = TableRegistry::getTableLocator()->get('CakeDC/Users.SocialAccounts') ->get('00000000-0000-0000-0000-000000000001', ['contain' => 'Users']); - $this->UsersMailer->expects($this->once()) + $this->Email->expects($this->once()) ->method('setTo') ->with('user-1@test.com') ->will($this->returnValue($this->Email)); @@ -112,10 +112,10 @@ public function testSocialAccountValidation() ->with('first1, Your social account validation link') ->will($this->returnValue($this->Email)); - $this->Email->expects($this->once()) + $this->UsersMailer->expects($this->once()) ->method('setViewVars') ->with(['user' => $social->user, 'socialAccount' => $social]) - ->will($this->returnValue($this->Email)); + ->will($this->returnValue($this->UsersMailer)); $this->invokeMethod($this->UsersMailer, 'socialAccountValidation', [$social->user, $social]); } @@ -134,7 +134,7 @@ public function testResetPassword() 'token' => '12345', ]; $user = $table->newEntity($data); - $this->UsersMailer->expects($this->once()) + $this->Email->expects($this->once()) ->method('setTo') ->with($user['email']) ->will($this->returnValue($this->Email)); @@ -144,10 +144,10 @@ public function testResetPassword() ->with('FirstName, Your reset password link') ->will($this->returnValue($this->Email)); - $this->Email->expects($this->once()) + $this->UsersMailer->expects($this->once()) ->method('setViewVars') ->with($data) - ->will($this->returnValue($this->Email)); + ->will($this->returnValue($this->UsersMailer)); $this->invokeMethod($this->UsersMailer, 'resetPassword', [$user]); } diff --git a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php index c1b848aec..decc19871 100644 --- a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php @@ -217,7 +217,7 @@ public function testSocialLoginExistingReferenceOkay($data, $options) 'credentials' => [ 'token' => 'aT0ken' . time(), 'secret' => 'AS3crEt' . time(), - 'expires' => 1458423682 + 'expires' => 1458423682, ], 'avatar' => 'http://localhost/avatar.jpg' . time(), 'link' => 'facebook-link' . time(), @@ -226,11 +226,11 @@ public function testSocialLoginExistingReferenceOkay($data, $options) 'bio' => 'This is a raw bio', 'extra' => 'value', 'foo' => 'bar', - ] + ], ]; $accountBefore = $this->Table->SocialAccounts->find()->where([ 'SocialAccounts.reference' => $data['id'], - 'SocialAccounts.provider' => $data['provider'] + 'SocialAccounts.provider' => $data['provider'], ])->firstOrFail(); $result = $this->Behavior->socialLogin($fullData + [], $options); $this->assertEquals($result->id, '00000000-0000-0000-0000-000000000002'); @@ -238,7 +238,7 @@ public function testSocialLoginExistingReferenceOkay($data, $options) $account = $this->Table->SocialAccounts->find()->where([ 'SocialAccounts.reference' => $data['id'], - 'SocialAccounts.provider' => $data['provider'] + 'SocialAccounts.provider' => $data['provider'], ])->firstOrFail(); $this->assertEquals($fullData['avatar'], $account->avatar); From c699b9a7c56f8177709b0dde068794dea2dacfe3 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 Oct 2019 16:23:22 -0300 Subject: [PATCH 424/685] cs fixes --- src/Model/Entity/User.php | 8 ++++++++ src/Model/Table/UsersTable.php | 6 ++++++ src/Shell/UsersShell.php | 16 ++++++++++++---- src/View/Helper/UserHelper.php | 7 +++---- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 40e7c5f33..37f09f9bc 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -20,6 +20,14 @@ /** * User Entity. + * + * @property string $email + * @property string $role + * @property string $username + * @property bool $is_superuser + * @property \Cake\I18n\Time token_expires + * @property string token + * @property array additional_data */ class User extends Entity { diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index abc1b3698..83c8ad049 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -30,6 +30,12 @@ * @method \CakeDC\Users\Model\Entity\User[] patchEntities($entities, array $data, array $options = []) * @method \CakeDC\Users\Model\Entity\User findOrCreate($search, callable $callback = null, $options = []) * + * @mixin \CakeDC\Users\Model\Behavior\AuthFinderBehavior + * @mixin \CakeDC\Users\Model\Behavior\LinkSocialBehavior + * @mixin \CakeDC\Users\Model\Behavior\PasswordBehavior + * @mixin \CakeDC\Users\Model\Behavior\RegisterBehavior + * @mixin \CakeDC\Users\Model\Behavior\SocialAccountBehavior + * @mixin \CakeDC\Users\Model\Behavior\SocialBehavior */ class UsersTable extends Table { diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index ee2158548..6446d09fa 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -309,7 +309,7 @@ protected function _createUser($template) $userEntity->role = $role; $savedUser = $this->Users->save($userEntity); - if (!empty($savedUser)) { + if (is_object($savedUser)) { if ($savedUser->is_superuser) { $this->out(__d('cake_d_c/users', 'Superuser added:')); } else { @@ -334,14 +334,19 @@ protected function _createUser($template) * * @param string $username username * @param array $data data - * @return bool + * @return \CakeDC\Users\Model\Entity\User|bool */ protected function _updateUser($username, $data) { $user = $this->Users->find()->where(['username' => $username])->first(); - if (empty($user)) { + if (!is_object($user)) { $this->abort(__d('cake_d_c/users', 'The user was not found.')); + + return false; } + /** + * @var \Cake\Datasource\EntityInterface $user + */ $user = $this->Users->patchEntity($user, $data); collection($data)->filter(function ($value, $field) use ($user) { return !$user->isAccessible($field); @@ -364,7 +369,10 @@ public function deleteUser() if (empty($username)) { $this->abort(__d('cake_d_c/users', 'Please enter a username.')); } - $user = $this->Users->find()->where(['username' => $username])->first(); + /** + * @var \Cake\Datasource\EntityInterface $user + */ + $user = $this->Users->find()->where(['username' => $username])->firstOrFail(); if (isset($this->Users->SocialAccounts)) { $this->Users->SocialAccounts->deleteAll(['user_id' => $user->id]); } diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 0617860ff..ebf01beb9 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -126,13 +126,12 @@ public function welcome() $profileUrl = Configure::read('Users.Profile.route'); $session = $this->getView()->getRequest()->getSession(); + $title = $session->read('Auth.User.first_name') ?: $session->read('Auth.User.username'); + $title = is_array($title) ? '-' : (string)$title; $label = __d( 'cake_d_c/users', 'Welcome, {0}', - $this->AuthLink->link( - $session->read('Auth.User.first_name') ?: $session->read('Auth.User.username'), - $profileUrl - ) + $this->AuthLink->link($title, $profileUrl) ); return $this->Html->tag('span', $label, ['class' => 'welcome']); From df379636486c512bda5e025b798e18ee55471a66 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 Oct 2019 16:29:27 -0300 Subject: [PATCH 425/685] phpstan is not working with phpdocs like '@property' and "@mixin" --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 02760e2c9..7a20fb1f8 100644 --- a/composer.json +++ b/composer.json @@ -75,8 +75,7 @@ "scripts": { "check": [ "@cs-check", - "@test", - "@stan" + "@test" ], "cs-check": "phpcs -p --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/", "cs-fix": "phpcbf --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/", From 66089f2bbc6951ad78743b758ab962a779be6c60 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 12 Oct 2019 16:39:51 -0300 Subject: [PATCH 426/685] fixing templates path after merge from develop --- src/Template/Email/html/reset_password.ctp | 36 -------- .../Email/html/social_account_validation.ctp | 41 --------- src/Template/Email/html/validation.ctp | 36 -------- src/Template/Email/text/reset_password.ctp | 30 ------- .../Email/text/social_account_validation.ctp | 32 ------- src/Template/Email/text/validation.ctp | 30 ------- 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 | 78 ---------------- src/Template/Users/index.ctp | 55 ------------ src/Template/Users/login.ctp | 50 ----------- src/Template/Users/profile.ctp | 78 ---------------- src/Template/Users/register.ctp | 39 -------- src/Template/Users/request_reset_password.ctp | 10 --- .../Users/resend_token_validation.ctp | 22 ----- src/Template/Users/social_email.ctp | 21 ----- src/Template/Users/u2f_authenticate.ctp | 59 ------------ src/Template/Users/u2f_register.ctp | 64 ------------- src/Template/Users/verify.ctp | 20 ----- src/Template/Users/view.ctp | 90 ------------------- templates/Users/add.php | 24 ++--- templates/Users/change_password.php | 10 +-- templates/Users/edit.php | 45 +++++----- templates/Users/index.php | 30 +++---- templates/Users/login.php | 18 ++-- templates/Users/profile.php | 26 +++--- templates/Users/register.php | 23 ++--- templates/Users/request_reset_password.php | 4 +- templates/Users/resend_token_validation.php | 10 +-- templates/Users/social_email.php | 8 +- templates/Users/u2f_authenticate.php | 10 +-- templates/Users/u2f_register.php | 8 +- templates/Users/verify.php | 4 +- templates/Users/view.php | 56 ++++++------ templates/email/html/reset_password.php | 13 +-- .../email/html/social_account_validation.php | 13 +-- templates/email/html/validation.php | 13 +-- templates/email/text/reset_password.php | 11 +-- .../email/text/social_account_validation.php | 11 +-- templates/email/text/validation.php | 11 +-- templates/layout/email/html/default.php | 4 +- templates/layout/email/text/default.php | 4 +- 44 files changed, 182 insertions(+), 1061 deletions(-) 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/u2f_authenticate.ctp delete mode 100644 src/Template/Users/u2f_register.ctp delete mode 100644 src/Template/Users/verify.ctp delete mode 100644 src/Template/Users/view.ctp diff --git a/src/Template/Email/html/reset_password.ctp b/src/Template/Email/html/reset_password.ctp deleted file mode 100644 index 36c3e11cc..000000000 --- a/src/Template/Email/html/reset_password.ctp +++ /dev/null @@ -1,36 +0,0 @@ - true, - 'prefix' => false, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'resetPassword', - isset($token) ? $token : '' -]; -?> -

- , -

-

- Html->link(__d('cake_d_c/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 fde01878c..000000000 --- a/src/Template/Email/html/social_account_validation.ctp +++ /dev/null @@ -1,41 +0,0 @@ - - -

- , -

-

- true, - 'prefix' => false, - '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 8b3ce9fb4..000000000 --- a/src/Template/Email/html/validation.ctp +++ /dev/null @@ -1,36 +0,0 @@ - true, - 'prefix' => false, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'validateEmail', - isset($token) ? $token : '' -]; -?> -

- , -

-

- Html->link(__d('cake_d_c/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 ddf3feea8..000000000 --- a/src/Template/Email/text/reset_password.ctp +++ /dev/null @@ -1,30 +0,0 @@ - true, - 'prefix' => false, - '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 7e3d5e5e4..000000000 --- a/src/Template/Email/text/social_account_validation.ctp +++ /dev/null @@ -1,32 +0,0 @@ - true, - 'prefix' => false, - '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 2b2b78cc3..000000000 --- a/src/Template/Email/text/validation.ctp +++ /dev/null @@ -1,30 +0,0 @@ - true, - 'prefix' => false, - '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 98d045608..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 4d493b97c..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 2b795d20b..000000000 --- a/src/Template/Users/add.ctp +++ /dev/null @@ -1,36 +0,0 @@ - -
-

-
    -
  • Html->link(__d('cake_d_c/users', 'List Users'), ['action' => 'index']) ?>
  • -
-
-
- Form->create(${$tableAlias}); ?> -
- - Form->control('username', ['label' => __d('cake_d_c/users', 'Username')]); - echo $this->Form->control('email', ['label' => __d('cake_d_c/users', 'Email')]); - echo $this->Form->control('password', ['label' => __d('cake_d_c/users', 'Password')]); - echo $this->Form->control('first_name', ['label' => __d('cake_d_c/users', 'First name')]); - echo $this->Form->control('last_name', ['label' => __d('cake_d_c/users', 'Last name')]); - echo $this->Form->control('active', [ - 'type' => 'checkbox', - 'label' => __d('cake_d_c/users', 'Active') - ]); - ?> -
- Form->button(__d('cake_d_c/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 7efba8f10..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('cake_d_c/users', 'Current password')]); - ?> - - Form->control('password', [ - 'type' => 'password', - 'required' => true, - 'label' => __d('cake_d_c/users', 'New password')]); - ?> - Form->control('password_confirm', [ - 'type' => 'password', - 'required' => true, - 'label' => __d('cake_d_c/users', 'Confirm password')]); - ?> - -
- Form->button(__d('cake_d_c/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 551076252..000000000 --- a/src/Template/Users/edit.ctp +++ /dev/null @@ -1,78 +0,0 @@ - -
-

-
    -
  • - Form->postLink( - __d('cake_d_c/users', 'Delete'), - ['action' => 'delete', $Users->id], - ['confirm' => __d('cake_d_c/users', 'Are you sure you want to delete # {0}?', $Users->id)] - ); - ?> -
  • -
  • Html->link(__d('cake_d_c/users', 'List Users'), ['action' => 'index']) ?>
  • -
-
-
- Form->create($Users); ?> -
- - Form->control('username', ['label' => __d('cake_d_c/users', 'Username')]); - echo $this->Form->control('email', ['label' => __d('cake_d_c/users', 'Email')]); - echo $this->Form->control('first_name', ['label' => __d('cake_d_c/users', 'First name')]); - echo $this->Form->control('last_name', ['label' => __d('cake_d_c/users', 'Last name')]); - echo $this->Form->control('token', ['label' => __d('cake_d_c/users', 'Token')]); - echo $this->Form->control('token_expires', [ - 'label' => __d('cake_d_c/users', 'Token expires') - ]); - echo $this->Form->control('api_token', [ - 'label' => __d('cake_d_c/users', 'API token') - ]); - echo $this->Form->control('activation_date', [ - 'label' => __d('cake_d_c/users', 'Activation date') - ]); - echo $this->Form->control('tos_date', [ - 'label' => __d('cake_d_c/users', 'TOS date') - ]); - echo $this->Form->control('active', [ - 'label' => __d('cake_d_c/users', 'Active') - ]); - ?> -
- Form->button(__d('cake_d_c/users', 'Submit')) ?> - Form->end() ?> - -
- Reset Google Authenticator - Form->postLink( - __d('cake_d_c/users', 'Reset Google Authenticator Token'), [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'resetOneTimePasswordAuthenticator', $Users->id - ], [ - 'class' => 'btn btn-danger', - 'confirm' => __d( - 'cake_d_c/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 273c5211c..000000000 --- a/src/Template/Users/index.ctp +++ /dev/null @@ -1,55 +0,0 @@ - -
-

-
    -
  • Html->link(__d('cake_d_c/users', 'New {0}', $tableAlias), ['action' => 'add']) ?>
  • -
-
-
-
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('username', ['label' => __d('cake_d_c/users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('cake_d_c/users', 'Email')]); + echo $this->Form->control('password', ['label' => __d('cake_d_c/users', 'Password')]); echo $this->Form->control('password_confirm', [ 'type' => 'password', - 'label' => __d('CakeDC/Users', 'Confirm password') + 'label' => __d('cake_d_c/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')]); + echo $this->Form->control('first_name', ['label' => __d('cake_d_c/users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('cake_d_c/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]); + echo $this->Form->control('tos', ['type' => 'checkbox', 'label' => __d('cake_d_c/users', 'Accept TOS conditions?'), 'required' => true]); } if (Configure::read('Users.reCaptcha.registration')) { echo $this->User->addReCaptcha(); } ?>
- Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->button(__d('cake_d_c/users', 'Submit')) ?> Form->end() ?> diff --git a/src/Template/Users/request_reset_password.ctp b/src/Template/Users/request_reset_password.ctp index e406ff573..5c6b2e18c 100644 --- a/src/Template/Users/request_reset_password.ctp +++ b/src/Template/Users/request_reset_password.ctp @@ -2,9 +2,9 @@ Flash->render('auth') ?> Form->create('User') ?>
- + Form->control('reference') ?>
- Form->button(__d('CakeDC/Users', 'Submit')); ?> + Form->button(__d('cake_d_c/users', 'Submit')); ?> Form->end() ?> diff --git a/src/Template/Users/resend_token_validation.ctp b/src/Template/Users/resend_token_validation.ctp index bd66fad8e..f08bcb883 100644 --- a/src/Template/Users/resend_token_validation.ctp +++ b/src/Template/Users/resend_token_validation.ctp @@ -12,11 +12,11 @@
Form->create($user); ?>
- + Form->control('reference', ['label' => __d('CakeDC/Users', 'Email or username')]); + echo $this->Form->control('reference', ['label' => __d('cake_d_c/users', 'Email or username')]); ?>
- Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->button(__d('cake_d_c/users', 'Submit')) ?> Form->end() ?>
diff --git a/src/Template/Users/social_email.ctp b/src/Template/Users/social_email.ctp index 05f1c2f80..f9807f4cb 100644 --- a/src/Template/Users/social_email.ctp +++ b/src/Template/Users/social_email.ctp @@ -13,9 +13,9 @@ Flash->render() ?> Form->create('User') ?>
- + Form->control('email') ?>
- Form->button(__d('CakeDC/Users', 'Submit')); ?> + Form->button(__d('cake_d_c/users', 'Submit')); ?> Form->end() ?> diff --git a/src/Template/Users/verify.ctp b/src/Template/Users/verify.ctp index f1f7d2524..78528a336 100644 --- a/src/Template/Users/verify.ctp +++ b/src/Template/Users/verify.ctp @@ -10,9 +10,9 @@

- Form->control('code', ['required' => true, 'label' => __d('CakeDC/Users', 'Verification Code')]) ?> + Form->control('code', ['required' => true, 'label' => __d('cake_d_c/users', 'Verification Code')]) ?> - Form->button(__d('CakeDC/Users', ' Verify'), ['class' => 'btn btn-primary']); ?> + Form->button(__d('cake_d_c/users', ' Verify'), ['class' => 'btn btn-primary']); ?> Form->end() ?> diff --git a/src/Template/Users/view.ctp b/src/Template/Users/view.ctp index e52b6376a..0d500d277 100644 --- a/src/Template/Users/view.ctp +++ b/src/Template/Users/view.ctp @@ -12,68 +12,68 @@ $Users = ${$tableAlias}; ?>
-

+

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

provider) ?> Html->link( + $socialAccount->link && $socialAccount->link != '#' ? $this->Html->link( $linkText, $socialAccount->link, ['target' => '_blank'] - ) ?>
provider) ?> Html->link( + $socialAccount->link && $socialAccount->link != '#' ? $this->Html->link( $linkText, $socialAccount->link, ['target' => '_blank'] - ) ?>
- - - - - - - - - - - - - - - - - - - - - -
Paginator->sort('username', __d('cake_d_c/users', 'Username')) ?>Paginator->sort('email', __d('cake_d_c/users', 'Email')) ?>Paginator->sort('first_name', __d('cake_d_c/users', 'First name')) ?>Paginator->sort('last_name', __d('cake_d_c/users', 'Last name')) ?>
username) ?>email) ?>first_name) ?>last_name) ?> - Html->link(__d('cake_d_c/users', 'View'), ['action' => 'view', $user->id]) ?> - Html->link(__d('cake_d_c/users', 'Change password'), ['action' => 'changePassword', $user->id]) ?> - Html->link(__d('cake_d_c/users', 'Edit'), ['action' => 'edit', $user->id]) ?> - Form->postLink(__d('cake_d_c/users', 'Delete'), ['action' => 'delete', $user->id], ['confirm' => __d('cake_d_c/users', 'Are you sure you want to delete # {0}?', $user->id)]) ?> -
-
-
    - Paginator->prev('< ' . __d('cake_d_c/users', 'previous')) ?> - Paginator->numbers() ?> - Paginator->next(__d('cake_d_c/users', 'next') . ' >') ?> -
-

Paginator->counter() ?>

-
-
diff --git a/src/Template/Users/login.ctp b/src/Template/Users/login.ctp deleted file mode 100644 index 99aaf4edd..000000000 --- a/src/Template/Users/login.ctp +++ /dev/null @@ -1,50 +0,0 @@ - -
- Flash->render('auth') ?> - Form->create() ?> -
- - Form->control('username', ['label' => __d('cake_d_c/users', 'Username'), 'required' => true]) ?> - Form->control('password', ['label' => __d('cake_d_c/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('cake_d_c/users', 'Remember me'), - 'checked' => Configure::read('Users.RememberMe.checked') - ]); - } - ?> - Html->link(__d('cake_d_c/users', 'Register'), ['action' => 'register']); - } - if (Configure::read('Users.Email.required')) { - if ($registrationActive) { - echo ' | '; - } - echo $this->Html->link(__d('cake_d_c/users', 'Reset Password'), ['action' => 'requestResetPassword']); - } - ?> -
- User->socialLoginList()); ?> - Form->button(__d('cake_d_c/users', 'Login')); ?> - Form->end() ?> -
diff --git a/src/Template/Users/profile.ctp b/src/Template/Users/profile.ctp deleted file mode 100644 index bd786ffc1..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('cake_d_c/users', '{0} {1}', $user->first_name, $user->last_name), - ['class' => 'full_name'] - ) - ?> -

- - Html->link(__d('cake_d_c/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('cake_d_c/users', 'Link to {0}', h($socialAccount->provider)) : h($socialAccount->username) - ?> - - - - - - - -
Html->image( - $socialAccount->avatar, - ['width' => '90', 'height' => '90'] - ) ?> - provider) ?>link && $socialAccount->link != '#' ? $this->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 3ab7156ba..000000000 --- a/src/Template/Users/register.ctp +++ /dev/null @@ -1,39 +0,0 @@ - -
- Form->create($user); ?> -
- - Form->control('username', ['label' => __d('cake_d_c/users', 'Username')]); - echo $this->Form->control('email', ['label' => __d('cake_d_c/users', 'Email')]); - echo $this->Form->control('password', ['label' => __d('cake_d_c/users', 'Password')]); - echo $this->Form->control('password_confirm', [ - 'type' => 'password', - 'label' => __d('cake_d_c/users', 'Confirm password') - ]); - echo $this->Form->control('first_name', ['label' => __d('cake_d_c/users', 'First name')]); - echo $this->Form->control('last_name', ['label' => __d('cake_d_c/users', 'Last name')]); - if (Configure::read('Users.Tos.required')) { - echo $this->Form->control('tos', ['type' => 'checkbox', 'label' => __d('cake_d_c/users', 'Accept TOS conditions?'), 'required' => true]); - } - if (Configure::read('Users.reCaptcha.registration')) { - echo $this->User->addReCaptcha(); - } - ?> -
- Form->button(__d('cake_d_c/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 5c6b2e18c..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('cake_d_c/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 2023e3c18..000000000 --- a/src/Template/Users/resend_token_validation.ctp +++ /dev/null @@ -1,22 +0,0 @@ - -
- Form->create($user); ?> -
- - Form->control('reference', ['label' => __d('cake_d_c/users', 'Email or username')]); - ?> -
- Form->button(__d('cake_d_c/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 d0e3f68e2..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('cake_d_c/users', 'Submit')); ?> - Form->end() ?> -
diff --git a/src/Template/Users/u2f_authenticate.ctp b/src/Template/Users/u2f_authenticate.ctp deleted file mode 100644 index 0ec64aaa8..000000000 --- a/src/Template/Users/u2f_authenticate.ctp +++ /dev/null @@ -1,59 +0,0 @@ -Html->script('CakeDC/Users.u2f-api.js', ['block' => true]); -?> -
-
-
-
- Form->create(false, [ - 'url' => [ - 'action' => 'u2fAuthenticateFinish', - '?' => $this->request->getQueryParams() - ], - 'id' => 'u2fAuthenticateFrm' - ]) ?> - - Flash->render('auth') ?> - Flash->render() ?> -
-

-

-

-

-

Html->link( - __d('cake_d_c/users', 'Reload'), - ['action' => 'u2fAuthenticate'], - ['class' => 'btn btn-primary'] - )?>

-
- Form->hidden('authenticateResponse', ['secure' => false, 'id' => 'authenticateResponse'])?> - Form->end() ?> -
-
-
-
-Html->scriptStart(['block' => true]); -?> - setTimeout(function() { - var req = ; - var appId = req[0].appId; - var challenge = req[0].challenge; - - u2f.sign(appId, challenge, req, function(data) { - var targetForm = document.getElementById('u2fAuthenticateFrm'); - var targetInput = document.getElementById('authenticateResponse'); - if(data.errorCode && data.errorCode != 0) { - alert(""); - - return; - } - targetInput.value = JSON.stringify(data); - targetForm.submit(); - }); - }, 1000); -Html->scriptEnd();?> diff --git a/src/Template/Users/u2f_register.ctp b/src/Template/Users/u2f_register.ctp deleted file mode 100644 index 244505873..000000000 --- a/src/Template/Users/u2f_register.ctp +++ /dev/null @@ -1,64 +0,0 @@ -Html->script('CakeDC/Users.u2f-api.js', ['block' => true]); -?> -
-
-
-
- Form->create(false, [ - 'url' => [ - 'action' => 'u2fRegisterFinish', - '?' => $this->request->getQueryParams() - ], - 'id' => 'u2fRegisterFrm' - ]) ?> - - Flash->render('auth') ?> - Flash->render() ?> -
-

-

-

In order to enable your YubiKey the first step is to perform a registration.

-

When the YubiKey starts blinking, press the golden disc to activate it. Depending on the web browser you might need to confirm the use of extended information from the YubiKey.

-

Html->link( - __d('cake_d_c/users', 'Reload'), - ['action' => 'u2fRegister'], - ['class' => 'btn btn-primary'] - )?>

-
- Form->hidden('registerResponse', ['secure' => false, 'id' => 'registerResponse'])?> - Form->end() ?> -
-
-
-
- $registerRequest->appId, - 'version' => $registerRequest->version, - 'challenge' => $registerRequest->challenge, - 'attestation' => 'direct' -]); -$this->Html->scriptStart(['block' => true]); -?> -setTimeout(function() { - var req = ; - var appId = req.appId; - var registerRequests = [req]; - u2f.register(appId, registerRequests, [], function(data) { - var targetForm = document.getElementById('u2fRegisterFrm'); - var targetInput = document.getElementById('registerResponse'); - - if(data.errorCode && data.errorCode != 0) { - alert(""); - - return; - } - targetInput.value = JSON.stringify(data); - targetForm.submit(); - }); -}, 1000); -Html->scriptEnd();?> diff --git a/src/Template/Users/verify.ctp b/src/Template/Users/verify.ctp deleted file mode 100644 index 78528a336..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('cake_d_c/users', 'Verification Code')]) ?> -
- Form->button(__d('cake_d_c/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 9e0d28106..000000000 --- a/src/Template/Users/view.ctp +++ /dev/null @@ -1,90 +0,0 @@ - -
-

-
    -
  • Html->link(__d('cake_d_c/users', 'Edit User'), ['action' => 'edit', $Users->id]) ?>
  • -
  • Form->postLink( - __d('cake_d_c/users', 'Delete User'), - ['action' => 'delete', $Users->id], - ['confirm' => __d('cake_d_c/users', 'Are you sure you want to delete # {0}?', $Users->id)] - ) ?>
  • -
  • Html->link(__d('cake_d_c/users', 'List Users'), ['action' => 'index']) ?>
  • -
  • Html->link(__d('cake_d_c/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/templates/Users/add.php b/templates/Users/add.php index 751b2f3c6..2b795d20b 100644 --- a/templates/Users/add.php +++ b/templates/Users/add.php @@ -1,36 +1,36 @@
-

+

    -
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • +
  • Html->link(__d('cake_d_c/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('username', ['label' => __d('cake_d_c/users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('cake_d_c/users', 'Email')]); + echo $this->Form->control('password', ['label' => __d('cake_d_c/users', 'Password')]); + echo $this->Form->control('first_name', ['label' => __d('cake_d_c/users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('cake_d_c/users', 'Last name')]); echo $this->Form->control('active', [ 'type' => 'checkbox', - 'label' => __d('CakeDC/Users', 'Active') + 'label' => __d('cake_d_c/users', 'Active') ]); ?>
- Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->button(__d('cake_d_c/users', 'Submit')) ?> Form->end() ?>
diff --git a/templates/Users/change_password.php b/templates/Users/change_password.php index 339f2fc65..7efba8f10 100644 --- a/templates/Users/change_password.php +++ b/templates/Users/change_password.php @@ -2,26 +2,26 @@ Flash->render('auth') ?> Form->create($user) ?>
- + Form->control('current_password', [ 'type' => 'password', 'required' => true, - 'label' => __d('CakeDC/Users', 'Current password')]); + 'label' => __d('cake_d_c/users', 'Current password')]); ?> Form->control('password', [ 'type' => 'password', 'required' => true, - 'label' => __d('CakeDC/Users', 'New password')]); + 'label' => __d('cake_d_c/users', 'New password')]); ?> Form->control('password_confirm', [ 'type' => 'password', 'required' => true, - 'label' => __d('CakeDC/Users', 'Confirm password')]); + 'label' => __d('cake_d_c/users', 'Confirm password')]); ?>
- Form->button(__d('CakeDC/Users', 'Submit')); ?> + Form->button(__d('cake_d_c/users', 'Submit')); ?> Form->end() ?>
\ No newline at end of file diff --git a/templates/Users/edit.php b/templates/Users/edit.php index 91794b822..551076252 100644 --- a/templates/Users/edit.php +++ b/templates/Users/edit.php @@ -1,73 +1,74 @@
-

+

  • Form->postLink( - __d('CakeDC/Users', 'Delete'), + __d('cake_d_c/users', 'Delete'), ['action' => 'delete', $Users->id], - ['confirm' => __d('CakeDC/Users', 'Are you sure you want to delete # {0}?', $Users->id)] + ['confirm' => __d('cake_d_c/users', 'Are you sure you want to delete # {0}?', $Users->id)] ); ?>
  • -
  • Html->link(__d('CakeDC/Users', 'List Users'), ['action' => 'index']) ?>
  • +
  • Html->link(__d('cake_d_c/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('username', ['label' => __d('cake_d_c/users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('cake_d_c/users', 'Email')]); + echo $this->Form->control('first_name', ['label' => __d('cake_d_c/users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('cake_d_c/users', 'Last name')]); + echo $this->Form->control('token', ['label' => __d('cake_d_c/users', 'Token')]); echo $this->Form->control('token_expires', [ - 'label' => __d('CakeDC/Users', 'Token expires') + 'label' => __d('cake_d_c/users', 'Token expires') ]); echo $this->Form->control('api_token', [ - 'label' => __d('CakeDC/Users', 'API token') + 'label' => __d('cake_d_c/users', 'API token') ]); echo $this->Form->control('activation_date', [ - 'label' => __d('CakeDC/Users', 'Activation date') + 'label' => __d('cake_d_c/users', 'Activation date') ]); echo $this->Form->control('tos_date', [ - 'label' => __d('CakeDC/Users', 'TOS date') + 'label' => __d('cake_d_c/users', 'TOS date') ]); echo $this->Form->control('active', [ - 'label' => __d('CakeDC/Users', 'Active') + 'label' => __d('cake_d_c/users', 'Active') ]); ?>
- Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->button(__d('cake_d_c/users', 'Submit')) ?> Form->end() ?> - +
Reset Google Authenticator Form->postLink( - __d('CakeDC/Users', 'Reset Google Authenticator Token'), [ + __d('cake_d_c/users', 'Reset Google Authenticator Token'), [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', - 'action' => 'resetGoogleAuthenticator', $Users->id + 'action' => 'resetOneTimePasswordAuthenticator', $Users->id ], [ 'class' => 'btn btn-danger', 'confirm' => __d( - 'CakeDC/Users', + 'cake_d_c/users', 'Are you sure you want to reset token for user "{0}"?', $Users->username ) ]); diff --git a/templates/Users/index.php b/templates/Users/index.php index 6c9e49871..273c5211c 100644 --- a/templates/Users/index.php +++ b/templates/Users/index.php @@ -1,29 +1,29 @@
-

+

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

Paginator->counter() ?>

diff --git a/templates/Users/login.php b/templates/Users/login.php index 5e08f7cd6..99aaf4edd 100644 --- a/templates/Users/login.php +++ b/templates/Users/login.php @@ -1,11 +1,11 @@ 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]) ?> + + Form->control('username', ['label' => __d('cake_d_c/users', 'Username'), 'required' => true]) ?> + Form->control('password', ['label' => __d('cake_d_c/users', 'Password'), 'required' => true]) ?> User->addReCaptcha(); @@ -26,7 +26,7 @@ if (Configure::read('Users.RememberMe.active')) { echo $this->Form->control(Configure::read('Users.Key.Data.rememberMe'), [ 'type' => 'checkbox', - 'label' => __d('CakeDC/Users', 'Remember me'), + 'label' => __d('cake_d_c/users', 'Remember me'), 'checked' => Configure::read('Users.RememberMe.checked') ]); } @@ -34,17 +34,17 @@ Html->link(__d('CakeDC/Users', 'Register'), ['action' => 'register']); + echo $this->Html->link(__d('cake_d_c/users', 'Register'), ['action' => 'register']); } if (Configure::read('Users.Email.required')) { if ($registrationActive) { echo ' | '; } - echo $this->Html->link(__d('CakeDC/Users', 'Reset Password'), ['action' => 'requestResetPassword']); + echo $this->Html->link(__d('cake_d_c/users', 'Reset Password'), ['action' => 'requestResetPassword']); } ?>
User->socialLoginList()); ?> - Form->button(__d('CakeDC/Users', 'Login')); ?> + Form->button(__d('cake_d_c/users', 'Login')); ?> Form->end() ?>
diff --git a/templates/Users/profile.php b/templates/Users/profile.php index 8b59d9ee2..bd786ffc1 100644 --- a/templates/Users/profile.php +++ b/templates/Users/profile.php @@ -1,11 +1,11 @@ @@ -18,37 +18,37 @@ Html->tag( 'span', - __d('CakeDC/Users', '{0} {1}', $user->first_name, $user->last_name), + __d('cake_d_c/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']); ?> + Html->link(__d('cake_d_c/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) + $linkText = empty($escapedUsername) ? __d('cake_d_c/users', 'Link to {0}', h($socialAccount->provider)) : h($socialAccount->username) ?> + ) : '-' ?>
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('username', ['label' => __d('cake_d_c/users', 'Username')]); + echo $this->Form->control('email', ['label' => __d('cake_d_c/users', 'Email')]); + echo $this->Form->control('password', ['label' => __d('cake_d_c/users', 'Password')]); echo $this->Form->control('password_confirm', [ 'type' => 'password', - 'label' => __d('CakeDC/Users', 'Confirm password') + 'label' => __d('cake_d_c/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')]); + echo $this->Form->control('first_name', ['label' => __d('cake_d_c/users', 'First name')]); + echo $this->Form->control('last_name', ['label' => __d('cake_d_c/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]); + echo $this->Form->control('tos', ['type' => 'checkbox', 'label' => __d('cake_d_c/users', 'Accept TOS conditions?'), 'required' => true]); } if (Configure::read('Users.reCaptcha.registration')) { echo $this->User->addReCaptcha(); } ?>
- Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->button(__d('cake_d_c/users', 'Submit')) ?> Form->end() ?>
diff --git a/templates/Users/request_reset_password.php b/templates/Users/request_reset_password.php index e406ff573..5c6b2e18c 100644 --- a/templates/Users/request_reset_password.php +++ b/templates/Users/request_reset_password.php @@ -2,9 +2,9 @@ Flash->render('auth') ?> Form->create('User') ?>
- + Form->control('reference') ?>
- Form->button(__d('CakeDC/Users', 'Submit')); ?> + Form->button(__d('cake_d_c/users', 'Submit')); ?> Form->end() ?> diff --git a/templates/Users/resend_token_validation.php b/templates/Users/resend_token_validation.php index 2d2680fbe..2023e3c18 100644 --- a/templates/Users/resend_token_validation.php +++ b/templates/Users/resend_token_validation.php @@ -1,22 +1,22 @@
Form->create($user); ?>
- + Form->control('reference', ['label' => __d('CakeDC/Users', 'Email or username')]); + echo $this->Form->control('reference', ['label' => __d('cake_d_c/users', 'Email or username')]); ?>
- Form->button(__d('CakeDC/Users', 'Submit')) ?> + Form->button(__d('cake_d_c/users', 'Submit')) ?> Form->end() ?>
diff --git a/templates/Users/social_email.php b/templates/Users/social_email.php index b0a272b6d..d0e3f68e2 100644 --- a/templates/Users/social_email.php +++ b/templates/Users/social_email.php @@ -1,11 +1,11 @@ @@ -13,9 +13,9 @@ Flash->render() ?> Form->create('User') ?>
- + Form->control('email') ?>
- Form->button(__d('CakeDC/Users', 'Submit')); ?> + Form->button(__d('cake_d_c/users', 'Submit')); ?> Form->end() ?> diff --git a/templates/Users/u2f_authenticate.php b/templates/Users/u2f_authenticate.php index 0ae1bbb7a..0ec64aaa8 100644 --- a/templates/Users/u2f_authenticate.php +++ b/templates/Users/u2f_authenticate.php @@ -19,12 +19,12 @@ Flash->render('auth') ?> Flash->render() ?>
-

-

+

+

-

+

Html->link( - __('Reload'), + __d('cake_d_c/users', 'Reload'), ['action' => 'u2fAuthenticate'], ['class' => 'btn btn-primary'] )?>

@@ -48,7 +48,7 @@ var targetForm = document.getElementById('u2fAuthenticateFrm'); var targetInput = document.getElementById('authenticateResponse'); if(data.errorCode && data.errorCode != 0) { - alert(""); + alert(""); return; } diff --git a/templates/Users/u2f_register.php b/templates/Users/u2f_register.php index e487bcb2b..244505873 100644 --- a/templates/Users/u2f_register.php +++ b/templates/Users/u2f_register.php @@ -19,12 +19,12 @@ Flash->render('auth') ?> Flash->render() ?>
-

-

+

+

In order to enable your YubiKey the first step is to perform a registration.

When the YubiKey starts blinking, press the golden disc to activate it. Depending on the web browser you might need to confirm the use of extended information from the YubiKey.

Html->link( - __('Reload'), + __d('cake_d_c/users', 'Reload'), ['action' => 'u2fRegister'], ['class' => 'btn btn-primary'] )?>

@@ -53,7 +53,7 @@ var targetInput = document.getElementById('registerResponse'); if(data.errorCode && data.errorCode != 0) { - alert(""); + alert(""); return; } diff --git a/templates/Users/verify.php b/templates/Users/verify.php index f1f7d2524..78528a336 100644 --- a/templates/Users/verify.php +++ b/templates/Users/verify.php @@ -10,9 +10,9 @@

- Form->control('code', ['required' => true, 'label' => __d('CakeDC/Users', 'Verification Code')]) ?> + Form->control('code', ['required' => true, 'label' => __d('cake_d_c/users', 'Verification Code')]) ?>
- Form->button(__d('CakeDC/Users', ' Verify'), ['class' => 'btn btn-primary']); ?> + Form->button(__d('cake_d_c/users', ' Verify'), ['class' => 'btn btn-primary']); ?> Form->end() ?> diff --git a/templates/Users/view.php b/templates/Users/view.php index d2e21bf7a..9e0d28106 100644 --- a/templates/Users/view.php +++ b/templates/Users/view.php @@ -1,79 +1,79 @@
-

+

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

provider) ?> Html->link( + $socialAccount->link && $socialAccount->link != '#' ? $this->Html->link( $linkText, $socialAccount->link, ['target' => '_blank'] - ) ?>
- - - - - + + + + + social_accounts as $socialAccount) : ?> diff --git a/templates/email/html/reset_password.php b/templates/email/html/reset_password.php index f6055a1d4..36c3e11cc 100644 --- a/templates/email/html/reset_password.php +++ b/templates/email/html/reset_password.php @@ -1,16 +1,17 @@ true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetPassword', @@ -18,18 +19,18 @@ ]; ?>

- , + ,

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

Url->build($activationUrl) ) ?>

- , + ,

diff --git a/templates/email/html/social_account_validation.php b/templates/email/html/social_account_validation.php index acef3fbc5..fde01878c 100644 --- a/templates/email/html/social_account_validation.php +++ b/templates/email/html/social_account_validation.php @@ -1,23 +1,24 @@

- , + ,

true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'validateAccount', @@ -30,11 +31,11 @@

Url->build($activationUrl) ) ?>

- , + ,

diff --git a/templates/email/html/validation.php b/templates/email/html/validation.php index 8a1840468..8b3ce9fb4 100644 --- a/templates/email/html/validation.php +++ b/templates/email/html/validation.php @@ -1,16 +1,17 @@ true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', @@ -18,18 +19,18 @@ ]; ?>

- , + ,

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

Url->build($activationUrl) ) ?>

- , + ,

diff --git a/templates/email/text/reset_password.php b/templates/email/text/reset_password.php index 96f001565..ddf3feea8 100644 --- a/templates/email/text/reset_password.php +++ b/templates/email/text/reset_password.php @@ -1,29 +1,30 @@ true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetPassword', isset($token) ? $token : '' ]; ?> -, +, Url->build($activationUrl) ) ?> -, +, diff --git a/templates/email/text/social_account_validation.php b/templates/email/text/social_account_validation.php index 87e2d6813..7e3d5e5e4 100644 --- a/templates/email/text/social_account_validation.php +++ b/templates/email/text/social_account_validation.php @@ -1,16 +1,17 @@ true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'validateAccount', @@ -19,13 +20,13 @@ $socialAccount['token'], ]; ?> -, +, Url->build($activationUrl) ) ?> -, +, diff --git a/templates/email/text/validation.php b/templates/email/text/validation.php index ecf9d96a8..2b2b78cc3 100644 --- a/templates/email/text/validation.php +++ b/templates/email/text/validation.php @@ -1,29 +1,30 @@ true, + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', isset($token) ? $token : '' ]; ?> -, +, Url->build($activationUrl) ) ?> -, +, diff --git a/templates/layout/email/html/default.php b/templates/layout/email/html/default.php index b0c828681..98d045608 100644 --- a/templates/layout/email/html/default.php +++ b/templates/layout/email/html/default.php @@ -1,11 +1,11 @@ diff --git a/templates/layout/email/text/default.php b/templates/layout/email/text/default.php index 686aa84ab..4d493b97c 100644 --- a/templates/layout/email/text/default.php +++ b/templates/layout/email/text/default.php @@ -1,11 +1,11 @@ From 279b06daa0beb69a8dc32e6b8556b776f0d30ad8 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 20 Oct 2019 15:25:47 -0300 Subject: [PATCH 427/685] Added function to setup config related to users url. --- src/Utility/UsersUrl.php | 65 ++++++++++++++++++++++--- tests/TestCase/Utility/UsersUrlTest.php | 37 +++++++++++--- 2 files changed, 89 insertions(+), 13 deletions(-) diff --git a/src/Utility/UsersUrl.php b/src/Utility/UsersUrl.php index 0299ae885..de7b20eca 100644 --- a/src/Utility/UsersUrl.php +++ b/src/Utility/UsersUrl.php @@ -17,6 +17,17 @@ class UsersUrl { + /** + * Check if users url uses a custom controller. + * + * @return bool + */ + public static function isCustom() + { + $controller = Configure::read('Users.controller', 'CakeDC/Users.Users'); + + return $controller !== 'CakeDC/Users.Users'; + } /** * Get an user action url * @@ -25,12 +36,16 @@ class UsersUrl * * @return array */ - public function actionUrl($action, $extra = []) + public static function actionUrl($action, $extra = []) { - $prefix = false; + $prefix = null; $controller = Configure::read('Users.controller', 'CakeDC/Users.Users'); list($plugin, $controller) = pluginSplit($controller); - $plugin = $plugin ? $plugin : false; + $parts = explode('/', $controller); + if (isset($parts[1])) { + $controller = $parts[1]; + $prefix = $parts[0]; + } return compact('prefix', 'plugin', 'controller', 'action') + $extra; } @@ -43,15 +58,53 @@ public function actionUrl($action, $extra = []) * * @return bool */ - public function checkActionOnRequest($action, ServerRequest $request) + public static function checkActionOnRequest($action, ServerRequest $request) { - $url = $this->actionUrl($action); + $url = static::actionUrl($action); foreach ($url as $param => $value) { - if ($request->getParam($param) !== $value) { + if ($request->getParam($param, null) !== $value) { return false; } } return true; } + + /** + * Setup needed config urls but without overwriting + * + * @return void + */ + public static function setupConfigUrls() + { + $urls = self::getDefaultConfigUrls(); + foreach ($urls as $configKey => $url) { + if (!Configure::check($configKey)) { + Configure::write($configKey, $url); + } + } + } + + /** + * Get a list of default config urls using static::actionUrl method for users url. + * + * @return array + */ + private static function getDefaultConfigUrls() + { + $loginAction = static::actionUrl('login'); + + return [ + 'Users.Profile.route' => static::actionUrl('profile'), + 'OneTimePasswordAuthenticator.verifyAction' => static::actionUrl('verify'), + 'U2f.startAction' => static::actionUrl('u2f'), + 'Auth.AuthenticationComponent.loginAction' => $loginAction, + 'Auth.AuthenticationComponent.logoutRedirect' => $loginAction, + 'Auth.Authenticators.Form.loginUrl' => $loginAction, + 'Auth.Authenticators.Cookie.loginUrl' => $loginAction, + 'Auth.Authenticators.SocialPendingEmail.loginUrl' => $loginAction, + 'Auth.AuthorizationMiddleware.unauthorizedHandler.url' => $loginAction, + 'OAuth.path' => static::actionUrl('socialLogin'), + ]; + } } diff --git a/tests/TestCase/Utility/UsersUrlTest.php b/tests/TestCase/Utility/UsersUrlTest.php index bcd7d740c..732bf427a 100644 --- a/tests/TestCase/Utility/UsersUrlTest.php +++ b/tests/TestCase/Utility/UsersUrlTest.php @@ -76,7 +76,32 @@ public function dataProviderActionUrl() ['add', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'add'], 'Users'], ['edit', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'edit'], 'Users'], ['delete', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'delete'], 'Users'], - ['socialEmail', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'socialEmail'], 'Users'] + ['socialEmail', ['prefix' => false, 'plugin' => false, 'controller' => 'Users', 'action' => 'socialEmail'], 'Users'], + + ['verify', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'verify'], 'Admin/Users'], + ['linkSocial', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'linkSocial'], 'Admin/Users'], + ['callbackLinkSocial', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'callbackLinkSocial'], 'Admin/Users'], + ['socialLogin', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'socialLogin'], 'Admin/Users'], + ['login', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'login'], 'Admin/Users'], + ['logout', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'logout'], 'Admin/Users'], + ['getUsersTable', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'getUsersTable'], 'Admin/Users'], + ['setUsersTable', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'setUsersTable'], 'Admin/Users'], + ['profile', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'profile'], 'Admin/Users'], + ['validateReCaptcha', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'validateReCaptcha'], 'Admin/Users'], + ['register', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'register'], 'Admin/Users'], + ['validateEmail', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'validateEmail'], 'Admin/Users'], + ['changePassword', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'changePassword'], 'Admin/Users'], + ['resetPassword', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'resetPassword'], 'Admin/Users'], + ['requestResetPassword', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'requestResetPassword'], 'Admin/Users'], + ['resetOneTimePasswordAuthenticator', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'resetOneTimePasswordAuthenticator'], 'Admin/Users'], + ['validate', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'validate'], 'Admin/Users'], + ['resendTokenValidation', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'resendTokenValidation'], 'Admin/Users'], + ['index', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'index'], 'Admin/Users'], + ['view', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'view'], 'Admin/Users'], + ['add', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'add'], 'Admin/Users'], + ['edit', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'edit'], 'Admin/Users'], + ['delete', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'delete'], 'Admin/Users'], + ['socialEmail', ['prefix' => 'Admin', 'plugin' => false, 'controller' => 'Users', 'action' => 'socialEmail'], 'Admin/Users'] ]; } @@ -91,9 +116,8 @@ public function dataProviderActionUrl() */ public function testActionUrl($action, $expected, $controller = null) { - $UsersUrl = new UsersUrl(); Configure::write('Users.controller', $controller); - $actual = $UsersUrl->actionUrl($action); + $actual = UsersUrl::actionUrl($action); $this->assertEquals($expected, $actual); } @@ -119,7 +143,7 @@ public function dataProviderCheckActionOnRequest() ], [ 'socialLogin', - ['plugin' => false, 'controller' => 'Users', 'action' => 'socialLogin', 'provider' => 'facebook'], + ['plugin' => null, 'controller' => 'Users', 'action' => 'socialLogin', 'provider' => 'facebook'], 'CakeDC/Users.Users', false, ], @@ -131,7 +155,7 @@ public function dataProviderCheckActionOnRequest() ], [ 'socialLogin', - ['plugin' => false, 'controller' => 'Users', 'action' => 'socialLogin', 'provider' => 'facebook'], + ['plugin' => null, 'controller' => 'Users', 'action' => 'socialLogin', 'provider' => 'facebook'], 'Users', true, ], @@ -151,14 +175,13 @@ public function dataProviderCheckActionOnRequest() */ public function testCheckActionOnRequest($action, $params, $controller, $expected) { - $UsersUrl = new UsersUrl(); Configure::write('Users.controller', $controller); $uri = new Uri('/auth/facebook'); $request = ServerRequestFactory::fromGlobals(); $request = $request->withUri($uri); $request = $request->withAttribute('params', $params); - $actual = $UsersUrl->checkActionOnRequest($action, $request); + $actual = UsersUrl::checkActionOnRequest($action, $request); $this->assertSame($expected, $actual); } } From faabc5a9c4364ea53736fcce7deb161fe16844b2 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 20 Oct 2019 15:27:11 -0300 Subject: [PATCH 428/685] On bootstrap, setup configuration related to users url. --- config/bootstrap.php | 3 +++ config/users.php | 43 ------------------------------------------- 2 files changed, 3 insertions(+), 43 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index 9c4c7c99a..27c05c01c 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -9,6 +9,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +use CakeDC\Users\Utility\UsersUrl; use Cake\Core\Configure; use Cake\ORM\TableRegistry; use Cake\Routing\Router; @@ -17,6 +18,8 @@ collection((array)Configure::read('Users.config'))->each(function ($file) { Configure::load($file); }); +UsersUrl::setupConfigUrls(); + if (!TableRegistry::getTableLocator()->exists('Users')) { TableRegistry::getTableLocator()->setConfig('Users', ['className' => Configure::read('Users.table')]); } diff --git a/config/users.php b/config/users.php index 9f125fc43..5a0f3715d 100644 --- a/config/users.php +++ b/config/users.php @@ -62,7 +62,6 @@ 'Profile' => [ // Allow view other users profiles 'viewOthers' => true, - 'route' => ['prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], ], 'Key' => [ 'Session' => [ @@ -102,12 +101,6 @@ ], 'OneTimePasswordAuthenticator' => [ 'checker' => \CakeDC\Auth\Authentication\DefaultOneTimePasswordAuthenticationChecker::class, - 'verifyAction' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'verify', - 'prefix' => false, - ], 'login' => false, 'issuer' => null, // The number of digits the resulting codes will be @@ -124,12 +117,6 @@ 'U2f' => [ 'enabled' => false, 'checker' => \CakeDC\Auth\Authentication\DefaultU2fAuthenticationChecker::class, - 'startAction' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'u2f', - 'prefix' => false, - ] ], // default configuration used to auto-load the Auth Component, override to change the way Auth works 'Auth' => [ @@ -138,18 +125,6 @@ ], 'AuthenticationComponent' => [ 'load' => true, - 'loginAction' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - 'prefix' => false, - ], - 'logoutRedirect' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - 'prefix' => false, - ], 'loginRedirect' => '/', 'requireIdentity' => false ], @@ -162,12 +137,6 @@ 'Form' => [ 'className' => 'CakeDC/Auth.Form', 'urlChecker' => 'Authentication.CakeRouter', - 'loginUrl' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - 'prefix' => false, - ] ], 'Token' => [ 'className' => 'Authentication.Token', @@ -185,12 +154,6 @@ 'httpOnly' => true, ], 'urlChecker' => 'Authentication.CakeRouter', - 'loginUrl' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - 'prefix' => false, - ] ], 'Social' => [ 'className' => 'CakeDC/Users.Social', @@ -237,11 +200,6 @@ 'ForbiddenException' => 'Authorization\Exception\ForbiddenException', ], 'className' => 'Authorization.CakeRedirect', - 'url' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - ] ] ], 'AuthorizationComponent' => [ @@ -253,7 +211,6 @@ ] ], 'OAuth' => [ - 'path' => ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', 'prefix' => null], 'providers' => [ 'facebook' => [ 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', From 98fb181c38fb346a4fda90ae3036bea81bb70357 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 20 Oct 2019 15:27:47 -0300 Subject: [PATCH 429/685] On bootstrap, setup configuration related to users url. --- tests/TestCase/PluginTest.php | 66 +++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 4320c9e3b..82aa4ba9a 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -427,4 +427,70 @@ public function testGetAuthorizationServiceCallableDefined() $actualService = $plugin->getAuthorizationService($request, $response); $this->assertSame($service, $actualService); } + + /** + * test bootstrap method + * + * @param string $urlConfigKey The url config key. + * @param array $expectedUrl The expected url value for $urlConfigKey. + * @dataProvider dataProviderConfigUsersUrls + * @return void + */ + public function testBootstrap($urlConfigKey, $expectedUrl) + { + $actual = Configure::read($urlConfigKey); + $this->assertEquals($expectedUrl, $actual); + } + + /** + * Data provider for users urls + * + * @return array + */ + public function dataProviderConfigUsersUrls() + { + $defaultVerifyAction = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'verify', + 'prefix' => false, + ]; + $defaultProfileAction = [ + 'prefix' => false, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'profile' + ]; + $defaultU2fStartAction = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'u2f', + 'prefix' => false, + ]; + $defaultLoginAction = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'login', + 'prefix' => false, + ]; + $defaultOauthPath = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'socialLogin', + 'prefix' => false + ]; + return [ + ['Users.Profile.route', $defaultProfileAction], + ['OneTimePasswordAuthenticator.verifyAction', $defaultVerifyAction], + ['U2f.startAction', $defaultU2fStartAction], + ['Auth.AuthenticationComponent.loginAction', $defaultLoginAction], + ['Auth.AuthenticationComponent.logoutRedirect', $defaultLoginAction], + ['Auth.AuthenticationComponent.loginRedirect', '/'], + ['Auth.Authenticators.Form.loginUrl', $defaultLoginAction], + ['Auth.Authenticators.Cookie.loginUrl', $defaultLoginAction], + ['Auth.Authenticators.SocialPendingEmail.loginUrl', $defaultLoginAction], + ['Auth.AuthorizationMiddleware.unauthorizedHandler.url', $defaultLoginAction], + ['OAuth.path', $defaultOauthPath], + ]; + } } From fc2178f6125fd266e452d74edfbfc14f39a8489a Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 20 Oct 2019 15:28:41 -0300 Subject: [PATCH 430/685] Using custom url for routes. --- config/routes.php | 33 +++++++++---------------- src/Middleware/SocialAuthMiddleware.php | 2 +- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/config/routes.php b/config/routes.php index 83663ea1d..b43e0a804 100644 --- a/config/routes.php +++ b/config/routes.php @@ -8,14 +8,15 @@ * @copyright Copyright 2010 - 2018, Cake Development Corporation (https://www.cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +use CakeDC\Users\Utility\UsersUrl; use Cake\Core\Configure; use Cake\Routing\RouteBuilder; use Cake\Routing\Router; - -Router::plugin('CakeDC/Users', ['path' => '/users'], function (RouteBuilder $routes) { +//Use custom path if url is customized +$baseUsersPath = UsersUrl::isCustom() ? '/users-base' : '/users'; +Router::plugin('CakeDC/Users', ['path' => $baseUsersPath], function (RouteBuilder $routes) { $routes->fallbacks('DashedRoute'); }); - Router::connect('/accounts/validate/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', @@ -23,25 +24,13 @@ ]); // Google Authenticator related routes if (Configure::read('OneTimePasswordAuthenticator.login')) { - Router::connect('/verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify']); + Router::connect('/verify', UsersUrl::actionUrl('verify')); - Router::connect('/resetOneTimePasswordAuthenticator', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'resetOneTimePasswordAuthenticator' - ]); + Router::connect('/resetOneTimePasswordAuthenticator', UsersUrl::actionUrl('resetOneTimePasswordAuthenticator')); } -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', -]); +Router::connect('/profile/*', UsersUrl::actionUrl('profile')); +Router::connect('/login', UsersUrl::actionUrl('login')); +Router::connect('/logout', UsersUrl::actionUrl('logout')); +Router::connect('/link-social/*', UsersUrl::actionUrl('linkSocial')); +Router::connect('/callback-link-social/*', UsersUrl::actionUrl('callbackLinkSocial')); diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 2e15cbc03..669ead2ec 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -106,7 +106,7 @@ private function setErrorMessage(ServerRequest $request, $message) */ protected function responseWithActionLocation(ResponseInterface $response, $action) { - $url = Router::url((new UsersUrl())->actionUrl($action)); + $url = Router::url(UsersUrl::actionUrl($action)); return $response->withLocation($url); } From 7c1ad046b98a9ca3b47ec1d0d10f339b89cc70c0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 20 Oct 2019 17:13:46 -0300 Subject: [PATCH 431/685] Improved route params to avoid issue with authenticator --- config/routes.php | 14 ++-- src/Utility/UsersUrl.php | 23 +++++- tests/TestCase/PluginTest.php | 12 +-- tests/TestCase/Utility/UsersUrlTest.php | 103 +++++++++++++++++++++++- 4 files changed, 134 insertions(+), 18 deletions(-) diff --git a/config/routes.php b/config/routes.php index b43e0a804..3585f99dd 100644 --- a/config/routes.php +++ b/config/routes.php @@ -24,13 +24,13 @@ ]); // Google Authenticator related routes if (Configure::read('OneTimePasswordAuthenticator.login')) { - Router::connect('/verify', UsersUrl::actionUrl('verify')); + Router::connect('/verify', UsersUrl::actionParams('verify')); - Router::connect('/resetOneTimePasswordAuthenticator', UsersUrl::actionUrl('resetOneTimePasswordAuthenticator')); + Router::connect('/resetOneTimePasswordAuthenticator', UsersUrl::actionParams('resetOneTimePasswordAuthenticator')); } -Router::connect('/profile/*', UsersUrl::actionUrl('profile')); -Router::connect('/login', UsersUrl::actionUrl('login')); -Router::connect('/logout', UsersUrl::actionUrl('logout')); -Router::connect('/link-social/*', UsersUrl::actionUrl('linkSocial')); -Router::connect('/callback-link-social/*', UsersUrl::actionUrl('callbackLinkSocial')); +Router::connect('/profile/*', UsersUrl::actionParams('profile')); +Router::connect('/login', UsersUrl::actionParams('login')); +Router::connect('/logout', UsersUrl::actionParams('logout')); +Router::connect('/link-social/*', UsersUrl::actionParams('linkSocial')); +Router::connect('/callback-link-social/*', UsersUrl::actionParams('callbackLinkSocial')); diff --git a/src/Utility/UsersUrl.php b/src/Utility/UsersUrl.php index de7b20eca..5d0fbc9bc 100644 --- a/src/Utility/UsersUrl.php +++ b/src/Utility/UsersUrl.php @@ -37,6 +37,21 @@ public static function isCustom() * @return array */ public static function actionUrl($action, $extra = []) + { + $params = static::actionParams($action); + $params['prefix'] = $params['prefix'] ?: false; + $params['plugin'] = $params['plugin'] ?: false; + + return $params + $extra; + } + + /** + * Get an user action route. This should not be user for links like HtmlHelper::link + * + * @param string $action user action + * @return array + */ + public static function actionParams($action) { $prefix = null; $controller = Configure::read('Users.controller', 'CakeDC/Users.Users'); @@ -47,7 +62,7 @@ public static function actionUrl($action, $extra = []) $prefix = $parts[0]; } - return compact('prefix', 'plugin', 'controller', 'action') + $extra; + return compact('prefix', 'plugin', 'controller', 'action'); } /** @@ -60,8 +75,8 @@ public static function actionUrl($action, $extra = []) */ public static function checkActionOnRequest($action, ServerRequest $request) { - $url = static::actionUrl($action); - foreach ($url as $param => $value) { + $route = static::actionParams($action); + foreach ($route as $param => $value) { if ($request->getParam($param, null) !== $value) { return false; } @@ -104,7 +119,7 @@ private static function getDefaultConfigUrls() 'Auth.Authenticators.Cookie.loginUrl' => $loginAction, 'Auth.Authenticators.SocialPendingEmail.loginUrl' => $loginAction, 'Auth.AuthorizationMiddleware.unauthorizedHandler.url' => $loginAction, - 'OAuth.path' => static::actionUrl('socialLogin'), + 'OAuth.path' => static::actionParams('socialLogin'), ]; } } diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 82aa4ba9a..d45c88500 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -439,7 +439,7 @@ public function testGetAuthorizationServiceCallableDefined() public function testBootstrap($urlConfigKey, $expectedUrl) { $actual = Configure::read($urlConfigKey); - $this->assertEquals($expectedUrl, $actual); + $this->assertSame($expectedUrl, $actual); } /** @@ -450,34 +450,34 @@ public function testBootstrap($urlConfigKey, $expectedUrl) public function dataProviderConfigUsersUrls() { $defaultVerifyAction = [ + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify', - 'prefix' => false, ]; $defaultProfileAction = [ 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', - 'action' => 'profile' + 'action' => 'profile', ]; $defaultU2fStartAction = [ + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'u2f', - 'prefix' => false, ]; $defaultLoginAction = [ + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', - 'prefix' => false, ]; $defaultOauthPath = [ + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', - 'prefix' => false ]; return [ ['Users.Profile.route', $defaultProfileAction], diff --git a/tests/TestCase/Utility/UsersUrlTest.php b/tests/TestCase/Utility/UsersUrlTest.php index 732bf427a..dc7d10440 100644 --- a/tests/TestCase/Utility/UsersUrlTest.php +++ b/tests/TestCase/Utility/UsersUrlTest.php @@ -20,6 +20,107 @@ class UsersUrlTest extends TestCase { + /** + * Data provider for test testActionRoute + * + * @return array + */ + public function dataProviderActionRoute() + { + return [ + ['verify', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify'], null], + ['linkSocial', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial'], null], + ['callbackLinkSocial', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'callbackLinkSocial'], null], + ['socialLogin', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin'], null], + ['login', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login'], null], + ['logout', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout'], null], + ['getUsersTable', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'getUsersTable'], null], + ['setUsersTable', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'setUsersTable'], null], + ['profile', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], null], + ['validateReCaptcha', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateReCaptcha'], null], + ['register', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'register'], null], + ['validateEmail', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail'], null], + ['changePassword', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'changePassword'], null], + ['resetPassword', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetPassword'], null], + ['requestResetPassword', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'requestResetPassword'], null], + ['resetOneTimePasswordAuthenticator', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetOneTimePasswordAuthenticator'], null], + ['validate', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validate'], null], + ['resendTokenValidation', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resendTokenValidation'], null], + ['index', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'index'], null], + ['view', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'view'], null], + ['add', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'add'], null], + ['edit', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'edit'], null], + ['delete', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'delete'], null], + ['socialEmail', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail'], null], + + ['verify', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'verify'], 'Users'], + ['linkSocial', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'linkSocial'], 'Users'], + ['callbackLinkSocial', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'callbackLinkSocial'], 'Users'], + ['socialLogin', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'socialLogin'], 'Users'], + ['login', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'login'], 'Users'], + ['logout', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'logout'], 'Users'], + ['getUsersTable', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'getUsersTable'], 'Users'], + ['setUsersTable', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'setUsersTable'], 'Users'], + ['profile', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'profile'], 'Users'], + ['validateReCaptcha', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'validateReCaptcha'], 'Users'], + ['register', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'register'], 'Users'], + ['validateEmail', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'validateEmail'], 'Users'], + ['changePassword', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'changePassword'], 'Users'], + ['resetPassword', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'resetPassword'], 'Users'], + ['requestResetPassword', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'requestResetPassword'], 'Users'], + ['resetOneTimePasswordAuthenticator', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'resetOneTimePasswordAuthenticator'], 'Users'], + ['validate', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'validate'], 'Users'], + ['resendTokenValidation', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'resendTokenValidation'], 'Users'], + ['index', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'index'], 'Users'], + ['view', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'view'], 'Users'], + ['add', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'add'], 'Users'], + ['edit', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'edit'], 'Users'], + ['delete', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'delete'], 'Users'], + ['socialEmail', ['prefix' => null, 'plugin' => null, 'controller' => 'Users', 'action' => 'socialEmail'], 'Users'], + + ['verify', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'verify'], 'Admin/Users'], + ['linkSocial', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'linkSocial'], 'Admin/Users'], + ['callbackLinkSocial', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'callbackLinkSocial'], 'Admin/Users'], + ['socialLogin', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'socialLogin'], 'Admin/Users'], + ['login', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'login'], 'Admin/Users'], + ['logout', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'logout'], 'Admin/Users'], + ['getUsersTable', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'getUsersTable'], 'Admin/Users'], + ['setUsersTable', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'setUsersTable'], 'Admin/Users'], + ['profile', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'profile'], 'Admin/Users'], + ['validateReCaptcha', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'validateReCaptcha'], 'Admin/Users'], + ['register', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'register'], 'Admin/Users'], + ['validateEmail', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'validateEmail'], 'Admin/Users'], + ['changePassword', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'changePassword'], 'Admin/Users'], + ['resetPassword', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'resetPassword'], 'Admin/Users'], + ['requestResetPassword', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'requestResetPassword'], 'Admin/Users'], + ['resetOneTimePasswordAuthenticator', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'resetOneTimePasswordAuthenticator'], 'Admin/Users'], + ['validate', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'validate'], 'Admin/Users'], + ['resendTokenValidation', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'resendTokenValidation'], 'Admin/Users'], + ['index', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'index'], 'Admin/Users'], + ['view', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'view'], 'Admin/Users'], + ['add', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'add'], 'Admin/Users'], + ['edit', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'edit'], 'Admin/Users'], + ['delete', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'delete'], 'Admin/Users'], + ['socialEmail', ['prefix' => 'Admin', 'plugin' => null, 'controller' => 'Users', 'action' => 'socialEmail'], 'Admin/Users'] + ]; + } + + /** + * Test actionParams method + * + * @dataProvider dataProviderActionRoute + * @param string $action user action. + * @param array $expected expected url + * @param string $controller controller name for users, optional + * @return void + */ + public function testActionParams($action, $expected, $controller = null) + { + Configure::write('Users.controller', $controller); + $actual = UsersUrl::actionParams($action); + $this->assertSame($expected, $actual); + } + /** * Data provider for test testActionUrl * @@ -118,7 +219,7 @@ public function testActionUrl($action, $expected, $controller = null) { Configure::write('Users.controller', $controller); $actual = UsersUrl::actionUrl($action); - $this->assertEquals($expected, $actual); + $this->assertSame($expected, $actual); } /** From 5645cec0bf8ec0faf8c71da5dcf28be4101ec53b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 21 Oct 2019 16:58:50 -0300 Subject: [PATCH 432/685] Fixing tests --- tests/TestCase/PluginTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index d45c88500..66c11564f 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -474,7 +474,7 @@ public function dataProviderConfigUsersUrls() 'action' => 'login', ]; $defaultOauthPath = [ - 'prefix' => false, + 'prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin', From c6aa5bb90f9405e1c349cd33fae39bb55e2c32b5 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 21 Oct 2019 17:06:23 -0300 Subject: [PATCH 433/685] Updated doc for extending controller. Now we use auth plugins. --- Docs/Documentation/Extending-the-Plugin.md | 35 +++++++++++++++------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index ecdc9107d..f3be9ba45 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -123,12 +123,30 @@ class MyUsersController extends AppController { use LoginTrait; use RegisterTrait; + + /** + * Initialize + * + * @return void + */ + public function initialize() + { + parent::initialize(); + $this->loadComponent('CakeDC/Users.Setup'); + if ($this->components()->has('Security')) { + $this->Security->setConfig( + 'unlockedActions', + ['login', 'u2fRegister', 'u2fRegisterFinish', 'u2fAuthenticate', 'u2fAuthenticateFinish'] + ); + } + } -//add your new actions, override, etc here + //add your new actions, override, etc here } ``` -Don't forget to update the `Users.controller` configuration in `users.php` +Don't forget to update the `Users.controller` configuration in `users.php` this is +needed to setup correct url/route for authentication. ```php 'Users' => [ @@ -158,18 +176,13 @@ use Cake\Http\Exception\NotFoundException; trait ImpersonateTrait { /** - * Adding a new feature as an example: Impersonate another user + * Adding a new feature as an example: Review user * - * @param type $userId + * @param string $userId */ - public function impersonate($userId) + public function review($userId) { - $user = $this->getUsersTable()->find() - ->where(['id' => $userId]) - ->hydrate(false) - ->first(); - $this->Auth->setUser($user); - return $this->redirect('/'); + //Your review logic } } ``` From c807db9b204561ab2d92f88733633a9aefc7f274 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 21 Oct 2019 17:10:02 -0300 Subject: [PATCH 434/685] phpcs --- src/Utility/UsersUrl.php | 1 + tests/TestCase/PluginTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Utility/UsersUrl.php b/src/Utility/UsersUrl.php index 5d0fbc9bc..43f4812ba 100644 --- a/src/Utility/UsersUrl.php +++ b/src/Utility/UsersUrl.php @@ -28,6 +28,7 @@ public static function isCustom() return $controller !== 'CakeDC/Users.Users'; } + /** * Get an user action url * diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 66c11564f..b1d33b2eb 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -479,6 +479,7 @@ public function dataProviderConfigUsersUrls() 'controller' => 'Users', 'action' => 'socialLogin', ]; + return [ ['Users.Profile.route', $defaultProfileAction], ['OneTimePasswordAuthenticator.verifyAction', $defaultVerifyAction], From abd15171b8726e6ef4f70a42a2bd9d91278ccc35 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 21 Oct 2019 17:14:54 -0300 Subject: [PATCH 435/685] Usings custom class to get valid login url --- src/Controller/SocialAccountsController.php | 5 +++-- .../Controller/SocialAccountsControllerTest.php | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index fa33b8303..8dd4ac774 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -15,6 +15,7 @@ use CakeDC\Users\Model\Table\SocialAccountsTable; use Cake\Datasource\Exception\RecordNotFoundException; use Cake\Http\Response; +use CakeDC\Users\Utility\UsersUrl; /** * SocialAccounts Controller @@ -59,7 +60,7 @@ public function validateAccount($provider, $reference, $token) $this->Flash->error(__d('cake_d_c/users', 'Social Account could not be validated')); } - return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + return $this->redirect(UsersUrl::actionUrl('login')); } /** @@ -87,6 +88,6 @@ public function resendValidation($provider, $reference) $this->Flash->error(__d('cake_d_c/users', 'Email could not be resent')); } - return $this->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + return $this->redirect(UsersUrl::actionUrl('login')); } } diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index 04e3faafc..006c40b12 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -89,7 +89,7 @@ public function testValidateAccountHappy() { $this->Controller->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', 'prefix' => false]); $this->Controller->validateAccount('Facebook', 'reference-1-1234', 'token-1234'); $this->assertEquals('Account validated successfully', $this->Controller->request->getSession()->read('Flash.flash.0.message')); } @@ -103,7 +103,7 @@ public function testValidateAccountInvalidToken() { $this->Controller->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', 'prefix' => false]); $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')); } @@ -117,7 +117,7 @@ public function testValidateAccountAlreadyActive() { $this->Controller->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', 'prefix' => false]); $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); $this->assertEquals('Social Account already active', $this->Controller->request->getSession()->read('Flash.flash.0.message')); } @@ -139,7 +139,7 @@ public function testResendValidationHappy() ->will($this->returnValue(true)); $this->Controller->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', 'prefix' => false]); $this->Controller->resendValidation('Facebook', 'reference-1-1234'); $this->assertEquals('Email sent successfully', $this->Controller->request->getSession()->read('Flash.flash.0.message')); @@ -162,7 +162,7 @@ public function testResendValidationEmailError() ->will($this->returnValue(false)); $this->Controller->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', 'prefix' => false]); $this->Controller->resendValidation('Facebook', 'reference-1-1234'); $this->assertEquals('Email could not be sent', $this->Controller->request->getSession()->read('Flash.flash.0.message')); @@ -177,7 +177,7 @@ public function testResendValidationInvalid() { $this->Controller->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', 'prefix' => false]); $this->Controller->resendValidation('Facebook', 'reference-invalid'); $this->assertEquals('Invalid account', $this->Controller->request->getSession()->read('Flash.flash.0.message')); } @@ -191,7 +191,7 @@ public function testResendValidationAlreadyActive() { $this->Controller->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', 'prefix' => false]); $this->Controller->validateAccount('Twitter', 'reference-1-1234', 'token-1234'); $this->assertEquals('Social Account already active', $this->Controller->request->getSession()->read('Flash.flash.0.message')); } From 2af9f9a90017554eb690a3546943d8534ebe1a15 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 21 Oct 2019 17:18:15 -0300 Subject: [PATCH 436/685] Usings custom class to get valid login url --- src/Controller/Component/LoginComponent.php | 3 ++- src/Controller/SocialAccountsController.php | 2 +- tests/TestCase/Controller/Traits/LoginTraitTest.php | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index e2e20c4b6..dc689e020 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -16,6 +16,7 @@ use CakeDC\Users\Plugin; use Cake\Controller\Component; use Cake\Core\Configure; +use CakeDC\Users\Utility\UsersUrl; /** * LoginFailure component @@ -80,7 +81,7 @@ public function handleFailure($redirect = true) return null; } - return $controller->redirect(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']); + return $controller->redirect(UsersUrl::actionUrl('login')); } /** diff --git a/src/Controller/SocialAccountsController.php b/src/Controller/SocialAccountsController.php index 8dd4ac774..17e4d40a1 100644 --- a/src/Controller/SocialAccountsController.php +++ b/src/Controller/SocialAccountsController.php @@ -13,9 +13,9 @@ use CakeDC\Users\Exception\AccountAlreadyActiveException; use CakeDC\Users\Model\Table\SocialAccountsTable; +use CakeDC\Users\Utility\UsersUrl; use Cake\Datasource\Exception\RecordNotFoundException; use Cake\Http\Response; -use CakeDC\Users\Utility\UsersUrl; /** * SocialAccounts Controller diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 432f87996..d339604bf 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -439,7 +439,7 @@ public function testLogin($AuthClass, $resultStatus, $message, $method, $failure } else { $this->Trait->expects($this->once()) ->method('redirect') - ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login']) + ->with(['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', 'prefix' => false]) ->will($this->returnValue(new Response())); $result = $this->Trait->$method(); $this->assertInstanceOf(Response::class, $result); From db14bd4162a0159b24faa0125c6c0d40386f5bd1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 21 Oct 2019 17:22:12 -0300 Subject: [PATCH 437/685] phpcs --- src/Controller/Component/LoginComponent.php | 2 +- src/View/Helper/UserHelper.php | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index dc689e020..9463397f3 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -14,9 +14,9 @@ use Authentication\Authenticator\ResultInterface; use CakeDC\Auth\Authentication\AuthenticationService; use CakeDC\Users\Plugin; +use CakeDC\Users\Utility\UsersUrl; use Cake\Controller\Component; use Cake\Core\Configure; -use CakeDC\Users\Utility\UsersUrl; /** * LoginFailure component diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 30c8bbe27..bceedc811 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -11,6 +11,7 @@ namespace CakeDC\Users\View\Helper; +use CakeDC\Users\Utility\UsersUrl; use Cake\Core\Configure; use Cake\Utility\Hash; use Cake\Utility\Inflector; @@ -100,9 +101,10 @@ public function socialLoginList(array $providerOptions = []) */ public function logout($message = null, $options = []) { - return $this->AuthLink->link(empty($message) ? __d('cake_d_c/users', 'Logout') : $message, [ - 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout', - ], $options); + $url = UsersUrl::actionUrl('logout'); + $title = empty($message) ? __d('cake_d_c/users', 'Logout') : $message; + + return $this->AuthLink->link($title, $url, $options); } /** From 0e49e0d7ee128e6cc0346208ed27ef547925e2cd Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 21 Oct 2019 17:32:55 -0300 Subject: [PATCH 438/685] Extend plugin may require loading helpers --- Docs/Documentation/Extending-the-Plugin.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index f3be9ba45..d7eb296c6 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -158,6 +158,21 @@ needed to setup correct url/route for authentication. Note you'll need to **copy the Plugin templates** you need into your project src/Template/MyUsers/[action].ctp +You may also need to load some helpers in your AppView: + +```php + /** + * Initialization hook method. + * + * @return void + */ + public function initialize() + { + $this->loadHelper('CakeDC/Users.AuthLink'); + $this->loadHelper('CakeDC/Users.User'); + } +``` + Extending the Features in your controller ----------------------------- From 7f31a186c2a26accd57518d547c371e0a8e18ec5 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 22 Oct 2019 13:49:05 -0300 Subject: [PATCH 439/685] Users.controller on migration guide --- Docs/Documentation/Migration/8.x-9.0.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Docs/Documentation/Migration/8.x-9.0.md b/Docs/Documentation/Migration/8.x-9.0.md index e3425fc30..c89ab6b27 100644 --- a/Docs/Documentation/Migration/8.x-9.0.md +++ b/Docs/Documentation/Migration/8.x-9.0.md @@ -33,6 +33,30 @@ Auth.AuthorizationComponent * CakeDC/Auth was upgraded and now has a better way to handle social login. Oauth providers config like OAuth.providers.facebook requires two new config keys, 'service' and 'mapper'. +* Users.controller config now is also used in mapping users routes (/login, register). +You need to give permissions to your new controller actions. + +* Users controller rely on CakeDC/Users.Setup Component, when using a custom users controller make sure to load it. +```php + + /** + * Initialize + * + * @return void + */ + public function initialize() + { + parent::initialize(); + $this->loadComponent('CakeDC/Users.Setup'); + if ($this->components()->has('Security')) { + $this->Security->setConfig( + 'unlockedActions', + ['login', 'u2fRegister', 'u2fRegisterFinish', 'u2fAuthenticate', 'u2fAuthenticateFinish'] + ); + } + } +``` + Loading the Plugin ------------------ In this version you need to load the plugin in your [Application class](https://github.com/cakephp/app/blob/master/src/Application.php). From 2098db9af22628db51310ed7cc0987912875247e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 22 Oct 2019 14:34:37 -0300 Subject: [PATCH 440/685] Migration guide say to use CakePHP 4.x --- Docs/Documentation/Migration/8.x-9.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Migration/8.x-9.0.md b/Docs/Documentation/Migration/8.x-9.0.md index c89ab6b27..635dc7868 100644 --- a/Docs/Documentation/Migration/8.x-9.0.md +++ b/Docs/Documentation/Migration/8.x-9.0.md @@ -2,7 +2,7 @@ Migration 8.x to 9.0 ====================== 9.0 uses the new plugins cakephp/authentication[(read more)](../Authentication.md) and cakephp/authorization[(read more)](../Authorization.md) instead of CakePHP -Authentication component. This version is compatible with CakePHP ^3.6 and the plugin +Authentication component. This version is compatible with CakePHP 4.x and the plugin code was updated to remove all deprecations. Configuration file users.php From 4027d40c38a54a0544a1ab3fa1f406d4a00d2697 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 22 Oct 2019 14:51:26 -0300 Subject: [PATCH 441/685] Escape button title --- templates/Users/verify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/Users/verify.php b/templates/Users/verify.php index 78528a336..92648a029 100644 --- a/templates/Users/verify.php +++ b/templates/Users/verify.php @@ -12,7 +12,7 @@ Form->control('code', ['required' => true, 'label' => __d('cake_d_c/users', 'Verification Code')]) ?> - Form->button(__d('cake_d_c/users', ' Verify'), ['class' => 'btn btn-primary']); ?> + Form->button(__d('cake_d_c/users', ' Verify'), ['class' => 'btn btn-primary', 'escapeTitle' => false]); ?> Form->end() ?> From 879d906d4bd47d78a86d76508e69c5546eae01b8 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 31 Oct 2019 08:25:03 -0300 Subject: [PATCH 442/685] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 7d94e1e43..add86acf9 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,12 @@ CakeDC Users Plugin [![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) +Warning +------- + +**OUTDATED branch, please use the specific develop branch for each version, for example 8.x for the version 8 development** + + Versions and branches --------------------- From 4df1e272ac211e5b53d6250de0dc2ac039a0515d Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 8 Nov 2019 15:48:22 -0300 Subject: [PATCH 443/685] Fixed migration guide with removed config keys --- Docs/Documentation/Migration/8.x-9.0.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Migration/8.x-9.0.md b/Docs/Documentation/Migration/8.x-9.0.md index 635dc7868..b0f766412 100644 --- a/Docs/Documentation/Migration/8.x-9.0.md +++ b/Docs/Documentation/Migration/8.x-9.0.md @@ -15,11 +15,12 @@ config/users.php from this plugin. * Users.auth was removed since AuthComponent is not used; -* Users.Social.authenticator was removed in favor of Authenticators.CakeDC/Users.Social and -Identifiers.CakeDC/Users.Social; +* Users.Social.authenticator was removed in favor of Auth.Authenticators.Social and Auth.Identifiers.Social; * Users.GoogleAuthenticator was renamed to OneTimePasswordAuthenticator; +* GoogleAuthenticator was renamed to OneTimePasswordAuthenticator; + * Auth.authenticate was removed in favor of Auth.Authentication, Auth.AuthenticationComponent, Auth.Authenticators, Auth.Identifiers From 5fdef71cc1ce4b6ed05b65ae74622ccc76ae1846 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 8 Nov 2019 15:49:01 -0300 Subject: [PATCH 444/685] trigger error for removed config keys --- config/bootstrap.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index ec103204a..d78acc8b7 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -26,6 +26,16 @@ $locator->setConfig($modelKey, ['className' => Configure::read('Users.table')]); } } -if (Configure::check('Auth.authenticate') || Configure::check('Auth.authorize')) { - trigger_error("Users plugin configurations keys Auth.authenticate and Auth.authorize were removed, please check migration guide https://github.com/CakeDC/users/blob/master/Docs/Documentation/MigrationGuide.md'"); +$oldConfigs = [ + 'Users.auth', + 'Users.Social.authenticator', + 'Users.GoogleAuthenticator', + 'GoogleAuthenticator', + 'Auth.authenticate', + 'Auth.authorize', +]; +foreach ($oldConfigs as $configKey) { + if (Configure::check($configKey)) { + trigger_error(__("Users plugin configuration key \"{0}\" was removed, please check migration guide https://github.com/CakeDC/users/blob/master/Docs/Documentation/Migration/8.x-9.0.md", $configKey)); + } } From e1afcf671ea88f344b582a3439dc1fe54af448ca Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 8 Nov 2019 15:51:46 -0300 Subject: [PATCH 445/685] Removed invalid info --- Docs/Documentation/Authentication.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index c2e057b5e..45efe230c 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -32,18 +32,6 @@ The default configuration for Auth.AuthenticationComponent is: ``` [ 'load' => true, - 'loginAction' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - 'prefix' => false, - ], - 'logoutRedirect' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - 'prefix' => false, - ], 'loginRedirect' => '/', 'requireIdentity' => false ] From ba5d15dc6eee0201d36389ea01a8b33d88183573 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 8 Nov 2019 15:52:24 -0300 Subject: [PATCH 446/685] Fixed info for authenticators config --- Docs/Documentation/Authentication.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 45efe230c..e9df9412f 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -62,7 +62,8 @@ For example if you add JWT authenticator you can set: ``` $authenticators = Configure::read('Auth.Authenticators'); -$authenticators['Authentication.Jwt'] = [ +$authenticators['Jwt'] = [ + 'className' => 'Authentication.Jwt', 'queryParam' => 'token', 'skipTwoFactorVerify' => true, ]; From 218410f1fdaf21343269a8effc254d0a0efe1411 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 8 Nov 2019 15:53:58 -0300 Subject: [PATCH 447/685] Fixed info for identifiers config --- Docs/Documentation/Authentication.md | 29 +++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index e9df9412f..304d8e4dc 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -92,13 +92,28 @@ As you add more authenticators you may need to add identifiers, please check ide The default value for Auth.Identifiers is: ``` [ - 'Authentication.Password' => [], - "CakeDC/Users.Social" => [ - 'authFinder' => 'all' - ], at load authentication - service step method from plugin object - 'Authentication.Token' => [ - 'tokenField' => 'api_token' + 'Password' => [ + 'className' => 'Authentication.Password', + 'fields' => [ + 'username' => ['username', 'email'], + 'password' => 'password' + ], + 'resolver' => [ + 'className' => 'Authentication.Orm', + 'finder' => 'active' + ], + ], + "Social" => [ + 'className' => 'CakeDC/Users.Social', + 'authFinder' => 'active' + ], + 'Token' => [ + 'className' => 'Authentication.Token', + 'tokenField' => 'api_token', + 'resolver' => [ + 'className' => 'Authentication.Orm', + 'finder' => 'active' + ], ] ] ``` From 05690331a904885fdd0e90d94ac5ffe2ce5b5b29 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 8 Nov 2019 15:57:57 -0300 Subject: [PATCH 448/685] Fixed info for authorization config --- Docs/Documentation/Authorization.md | 7 +------ config/users.php | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md index 069570a1e..9a6f01771 100644 --- a/Docs/Documentation/Authorization.md +++ b/Docs/Documentation/Authorization.md @@ -28,12 +28,7 @@ The default configuration for authorization middleware is: 'MissingIdentityException' => 'Authorization\Exception\MissingIdentityException', 'ForbiddenException' => 'Authorization\Exception\ForbiddenException', ], - 'className' => 'Authorization.CakeRedirect', - 'url' => [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'login', - ] + 'className' => 'Authorization.CakeRedirect', ] ], ``` diff --git a/config/users.php b/config/users.php index 0ea64652f..a5192f8a8 100644 --- a/config/users.php +++ b/config/users.php @@ -133,7 +133,7 @@ 'className' => 'Authentication.Session', 'skipTwoFactorVerify' => true, 'sessionKey' => 'Auth', - ], + ], 'Form' => [ 'className' => 'CakeDC/Auth.Form', 'urlChecker' => 'Authentication.CakeRouter', From a2bfb7c56d674c365f13aaca80bedef2958df456 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 8 Nov 2019 16:20:44 -0300 Subject: [PATCH 449/685] Updated install doc --- Docs/Documentation/Installation.md | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 0c95dbf1e..4171bee7c 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -18,7 +18,7 @@ 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 +NOTE: you'll need to enable social login 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. ``` @@ -60,30 +60,11 @@ Ensure the Users Plugin is loaded in your src/Application.php file parent::bootstrap(); $this->addPlugin(\CakeDC\Users\Plugin::class); + // Uncomment the line below to load your custom users.php config file + //Configure::write('Users.config', ['users']); } ``` -In CakePHP 3.8 , this method is deprecated, load the plugin in /src/Application.php : - -``` -// In src/Application.php. Requires at least 3.6.0 -namespace App; -use Cake\Http\BaseApplication; - -class Application extends BaseApplication -{ - public function bootstrap() - { - parent::bootstrap(); - - // Load a plugin with a vendor namespace by 'short name' - $this->addPlugin('CakeDC/Users'); - Configure::write('Users.config', ['users']); - } -} -``` - - Creating Required Tables ------------------------ If you want to use the Users tables to store your users and social accounts: @@ -105,10 +86,10 @@ bin/cake users addSuperuser Customization ---------- -config/bootstrap.php +Application::bootstrap ``` +$this->addPlugin(\CakeDC\Users\Plugin::class); Configure::write('Users.config', ['users']); -Plugin::load('CakeDC/Users', ['routes' => true, 'bootstrap' => true]); Configure::write('Users.Social.login', true); //to enable social login ``` From 8468456902d448b85465c21812a2c0f50f942fe6 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Tue, 26 Nov 2019 10:56:55 +0300 Subject: [PATCH 450/685] fixing code standards --- .travis.yml | 24 +++++++++++++++++------- src/View/Helper/UserHelper.php | 1 - 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 39a9ec6c6..2e3e3715b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,26 @@ language: php -services: - - postgresql - - mysql + +dist: xenial + php: - 7.2 - 7.3 - + - '7.4snapshot' + sudo: false +services: + - postgresql + - mysql + +cache: + directories: + - vendor + - $HOME/.composer/cache + env: matrix: - - DB=mysql db_dsn='mysql://travis@127.0.0.1/cakephp_test' + - DB=mysql db_dsn='mysql://root@127.0.0.1/cakephp_test?init[]=SET sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"' - DB=pgsql db_dsn='postgres://postgres@127.0.0.1/cakephp_test' - DB=sqlite db_dsn='sqlite:///:memory:' @@ -33,8 +43,8 @@ matrix: before_script: - if [[ $TRAVIS_PHP_VERSION != 7.3 ]]; then phpenv config-rm xdebug.ini; fi - 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" + - if [[ $DB == 'mysql' ]]; then mysql -u root -e 'CREATE DATABASE cakephp_test;'; fi + - if [[ $DB == 'pgsql' ]]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi - if [[ $PHPSTAN = 1 ]]; then composer stan-setup; fi script: diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index e4a27a976..99d71cf4d 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -169,7 +169,6 @@ public function addReCaptcha() try { $this->Form->unlockField('g-recaptcha-response'); } catch (\Exception $e) { - } return $this->Html->tag('div', '', [ From 78243dd843a9df00ad3b0714e8dc12c276b2b4bb Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Tue, 26 Nov 2019 11:45:35 +0300 Subject: [PATCH 451/685] improve composer config --- composer.json | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 7a20fb1f8..81c692b23 100644 --- a/composer.json +++ b/composer.json @@ -46,9 +46,7 @@ "yubico/u2flib-server": "^1.0", "php-coveralls/php-coveralls": "^2.1", "league/oauth1-client": "^1.7", - "cakephp/cakephp-codesniffer": "dev-next", - "phpstan/phpstan": "0.11", - "vimeo/psalm": "3.0" + "cakephp/cakephp-codesniffer": "dev-next" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", @@ -77,12 +75,16 @@ "@cs-check", "@test" ], - "cs-check": "phpcs -p --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/", - "cs-fix": "phpcbf --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/", + "analyse": [ + "@stan", + "@psalm" + ], + "cs-check": "phpcs -n -p --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests", + "cs-fix": "phpcbf --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests", "test": "phpunit --stderr", - "stan": "phpstan analyse src/ && psalm --show-info=false", - "psalm": "psalm --show-info=false", - "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.11 vimeo/psalm:^3.0 && mv composer.backup composer.json", + "stan": "phpstan analyse src/", + "psalm": "php vendor/psalm/phar/psalm.phar --show-info=false src/ ", + "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan-shim:^0.11.18 psalm/phar:^3.5 && mv composer.backup composer.json", "rector": "rector process src/", "rector-setup": "cp composer.json composer.backup && composer require --dev rector/rector:^0.4.11 && mv composer.backup composer.json", "coverage-test": "phpunit --stderr --coverage-clover=clover.xml" From 8f7c44bc93a3b70170126deb3027815849efe18f Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Tue, 26 Nov 2019 11:55:51 +0300 Subject: [PATCH 452/685] travis fixes --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2e3e3715b..10cad1063 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,12 +36,11 @@ matrix: - php: 7.3 env: PHPSTAN=1 DEFAULT=0 - + - php: 7.3 - env: COVERAGE=1 DEFAULT=0 DB=mysql db_dsn='mysql://travis@0.0.0.0/cakephp_test' + env: COVERAGE=1 DEFAULT=0 DB=mysql db_dsn='mysql://root@127.0.0.1/cakephp_test?init[]=SET sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"' before_script: - - if [[ $TRAVIS_PHP_VERSION != 7.3 ]]; then phpenv config-rm xdebug.ini; fi - composer install --prefer-dist --no-interaction - if [[ $DB == 'mysql' ]]; then mysql -u root -e 'CREATE DATABASE cakephp_test;'; fi - if [[ $DB == 'pgsql' ]]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi @@ -53,5 +52,8 @@ script: - if [[ $PHPCS = 1 ]]; then composer cs-check; fi - if [[ $PHPSTAN = 1 ]]; then composer stan; fi +after_success: + - if [[ $COVERAGE = 1 ]]; then bash <(curl -s https://codecov.io/bash); fi + notifications: email: false From 9c8b063fb93dd29f303d302ec265fd833fb4ffaf Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Tue, 26 Nov 2019 12:07:45 +0300 Subject: [PATCH 453/685] fix failed test --- tests/TestCase/Controller/Traits/RegisterTraitTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index fcb08a03f..3e4c4304e 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -115,6 +115,9 @@ public function testRegisterWithEventFalseResult() ->method('redirect'); $this->Trait->getRequest()->expects($this->never()) ->method('is'); + $this->Trait->getRequest()->expects($this->once()) + ->method('getData') + ->will($this->returnValue([])); $this->Trait->register(); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); From 7bb8a1ee4fe2729a2c37c9205843b0f42ae2dfa6 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Tue, 26 Nov 2019 12:35:43 +0300 Subject: [PATCH 454/685] fix failed test --- src/Controller/Traits/RegisterTrait.php | 2 +- tests/TestCase/Controller/Traits/RegisterTraitTest.php | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index a3ab7ae4f..f48c553cf 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -69,7 +69,7 @@ public function register() $result = $event->getResult(); if ($result instanceof EntityInterface) { $data = $result->toArray(); - $data['password'] = $requestData['password']; //since password is a hidden property + $data['password'] = $requestData['password'] ?? null; //since password is a hidden property $userSaved = $usersTable->register($user, $data, $options); if ($userSaved) { return $this->_afterRegister($userSaved); diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 3e4c4304e..fcb08a03f 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -115,9 +115,6 @@ public function testRegisterWithEventFalseResult() ->method('redirect'); $this->Trait->getRequest()->expects($this->never()) ->method('is'); - $this->Trait->getRequest()->expects($this->once()) - ->method('getData') - ->will($this->returnValue([])); $this->Trait->register(); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); From 4821be7a9e8583a342fe1e79081b8d09647f0a1e Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Sun, 1 Dec 2019 14:23:45 +0300 Subject: [PATCH 455/685] create baselines for 4.x plugin --- composer.json | 11 +- phpstan-baseline.neon | 480 ++++++++++++++++++++ phpstan.neon | 3 + psalm-baseline.xml | 292 ++++++++++++ psalm.xml | 1 + src/Controller/Component/LoginComponent.php | 2 +- 6 files changed, 784 insertions(+), 5 deletions(-) create mode 100644 phpstan-baseline.neon create mode 100644 psalm-baseline.xml diff --git a/composer.json b/composer.json index 81c692b23..ac85a1902 100644 --- a/composer.json +++ b/composer.json @@ -71,20 +71,23 @@ } }, "scripts": { - "check": [ - "@cs-check", - "@test" - ], "analyse": [ "@stan", "@psalm" ], + "check": [ + "@cs-check", + "@test", + "@analyse" + ], "cs-check": "phpcs -n -p --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests", "cs-fix": "phpcbf --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests", "test": "phpunit --stderr", "stan": "phpstan analyse src/", "psalm": "php vendor/psalm/phar/psalm.phar --show-info=false src/ ", "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan-shim:^0.11.18 psalm/phar:^3.5 && mv composer.backup composer.json", + "stan-rebuild-baseline": "phpstan analyse --configuration phpstan.neon --error-format baselineNeon src/ > phpstan-baseline.neon", + "psalm-rebuild-baseline": "php vendor/psalm/phar/psalm.phar --show-info=false --set-baseline=psalm-baseline.xml src/", "rector": "rector process src/", "rector-setup": "cp composer.json composer.backup && composer require --dev rector/rector:^0.4.11 && mv composer.backup composer.json", "coverage-test": "phpunit --stderr --coverage-clover=clover.xml" diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 000000000..ce7a31ff2 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,480 @@ + + +parameters: + ignoreErrors: + - + message: "#^Access to an undefined property Cake\\\\Controller\\\\Controller\\:\\:\\$Authentication\\.$#" + count: 1 + path: src\Controller\Component\LoginComponent.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: src\Controller\Component\LoginComponent.php + + - + message: "#^Call to an undefined method Cake\\\\Controller\\\\Controller\\:\\:getUsersTable\\(\\)\\.$#" + count: 1 + path: src\Controller\Component\LoginComponent.php + + - + message: "#^Call to an undefined method CakeDC\\\\Users\\\\Model\\\\Table\\\\SocialAccountsTable\\:\\:validateAccount\\(\\)\\.$#" + count: 1 + path: src\Controller\SocialAccountsController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Controller\\\\SocialAccountsController\\:\\:validateAccount\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" + count: 1 + path: src\Controller\SocialAccountsController.php + + - + message: "#^Call to an undefined method CakeDC\\\\Users\\\\Model\\\\Table\\\\SocialAccountsTable\\:\\:resendValidation\\(\\)\\.$#" + count: 1 + path: src\Controller\SocialAccountsController.php + + - + message: "#^Parameter \\#1 \\$provider of method CakeDC\\\\Auth\\\\Social\\\\Service\\\\ServiceFactory\\:\\:createFromProvider\\(\\) expects string, string\\|null given\\.$#" + count: 2 + path: src\Controller\UsersController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:linkSocial\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:callbackLinkSocial\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" + count: 2 + path: src\Controller\UsersController.php + + - + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:linkSocialAccount\\(\\)\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Call to an undefined method Cake\\\\Controller\\\\Component\\:\\:handleLogin\\(\\)\\.$#" + count: 3 + path: src\Controller\UsersController.php + + - + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:\\$Authentication\\.$#" + count: 2 + path: src\Controller\UsersController.php + + - + message: "#^Cannot assign offset 'secret_verified' to array\\|string\\|null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Parameter \\#1 \\$user of method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:onVerifyGetSecret\\(\\) expects CakeDC\\\\Users\\\\Model\\\\Entity\\\\User, array\\|string\\|null given\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:\\$OneTimePasswordAuthenticator\\.$#" + count: 3 + path: src\Controller\UsersController.php + + - + message: "#^Offset 'email' does not exist on array\\|string\\|null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Cannot assign offset 'id' to array\\|string\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Offset 'id' does not exist on array\\|string\\|null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:onPostVerifyCode\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Parameter \\#2 \\$user of method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:onPostVerifyCodeOkay\\(\\) expects CakeDC\\\\Users\\\\Model\\\\Entity\\\\User, array\\|string\\|null given\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:onPostVerifyCodeOkay\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validationPasswordConfirm\\(\\)\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validationCurrentPassword\\(\\)\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:changePassword\\(\\)\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:resetToken\\(\\)\\.$#" + count: 2 + path: src\Controller\UsersController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:requestResetPassword\\(\\) should return Cake\\\\Http\\\\Response\\|void but returns Cake\\\\Http\\\\Response\\|null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Parameter \\#2 \\$options of method Cake\\\\Controller\\\\Component\\\\FlashComponent\\:\\:success\\(\\) expects array, string given\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Parameter \\#2 \\$options of method Cake\\\\Controller\\\\Component\\\\FlashComponent\\:\\:error\\(\\) expects array, string given\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Parameter \\#1 \\$url of method Cake\\\\Controller\\\\Controller\\:\\:redirect\\(\\) expects array\\|Psr\\\\Http\\\\Message\\\\UriInterface\\|string, string\\|null given\\.$#" + count: 3 + path: src\Controller\UsersController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:_getReCaptchaInstance\\(\\) should return ReCaptcha\\\\ReCaptcha but returns null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:register\\(\\)\\.$#" + count: 2 + path: src\Controller\UsersController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:_afterRegister\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Parameter \\#1 \\$object of method Cake\\\\Controller\\\\Controller\\:\\:paginate\\(\\) expects Cake\\\\ORM\\\\Query\\|Cake\\\\ORM\\\\Table\\|string\\|null, Cake\\\\Datasource\\\\RepositoryInterface given\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:delete\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:redirectWithQuery\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Parameter \\#1 \\$json of function json_decode expects string, array\\|string\\|null given\\.$#" + count: 2 + path: src\Controller\UsersController.php + + - + message: "#^Cannot assign offset 'id' to array\\|string\\|null\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$u2f_registration\\.$#" + count: 1 + path: src\Controller\UsersController.php + + - + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validate\\(\\)\\.$#" + count: 2 + path: src\Controller\UsersController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:validate\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" + count: 3 + path: src\Controller\UsersController.php + + - + message: "#^Method CakeDC\\\\Users\\\\Authenticator\\\\SocialPendingEmailAuthenticator\\:\\:_getReCaptchaInstance\\(\\) should return ReCaptcha\\\\ReCaptcha but returns null\\.$#" + count: 1 + path: src\Authenticator\SocialPendingEmailAuthenticator.php + + - + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:socialLogin\\(\\)\\.$#" + count: 1 + path: src\Identifier\SocialIdentifier.php + + - + message: "#^Parameter \\#1 \\$object of function get_class expects object, Throwable\\|null given\\.$#" + count: 1 + path: src\Middleware\SocialAuthMiddleware.php + + - + message: "#^Parameter \\#2 \\$request of method CakeDC\\\\Users\\\\Utility\\\\UsersUrl\\:\\:checkActionOnRequest\\(\\) expects Cake\\\\Http\\\\ServerRequest, Psr\\\\Http\\\\Message\\\\ServerRequestInterface given\\.$#" + count: 1 + path: src\Middleware\SocialAuthMiddleware.php + + - + message: "#^Parameter \\#1 \\$request of method CakeDC\\\\Users\\\\Middleware\\\\SocialAuthMiddleware\\:\\:goNext\\(\\) expects Cake\\\\Http\\\\ServerRequest, Psr\\\\Http\\\\Message\\\\ServerRequestInterface given\\.$#" + count: 1 + path: src\Middleware\SocialAuthMiddleware.php + + - + message: "#^Parameter \\#2 \\$request of method CakeDC\\\\Users\\\\Utility\\\\UsersUrl\\:\\:checkActionOnRequest\\(\\) expects Cake\\\\Http\\\\ServerRequest, Psr\\\\Http\\\\Message\\\\ServerRequestInterface given\\.$#" + count: 1 + path: src\Middleware\SocialEmailMiddleware.php + + - + message: "#^Parameter \\#1 \\$request of method CakeDC\\\\Users\\\\Middleware\\\\SocialAuthMiddleware\\:\\:goNext\\(\\) expects Cake\\\\Http\\\\ServerRequest, Psr\\\\Http\\\\Message\\\\ServerRequestInterface given\\.$#" + count: 1 + path: src\Middleware\SocialEmailMiddleware.php + + - + message: "#^Call to an undefined method Cake\\\\Datasource\\\\EntityInterface\\:\\:updateToken\\(\\)\\.$#" + count: 1 + path: src\Model\Behavior\BaseTokenBehavior.php + + - + message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\BaseTokenBehavior\\:\\:_removeValidationToken\\(\\) should return Cake\\\\Datasource\\\\EntityInterface but returns Cake\\\\Datasource\\\\EntityInterface\\|false\\.$#" + count: 1 + path: src\Model\Behavior\BaseTokenBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$SocialAccounts\\.$#" + count: 5 + path: src\Model\Behavior\LinkSocialBehavior.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: src\Model\Behavior\LinkSocialBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$social_accounts\\.$#" + count: 2 + path: src\Model\Behavior\LinkSocialBehavior.php + + - + message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\PasswordBehavior\\:\\:resetToken\\(\\) should return string but returns Cake\\\\Datasource\\\\EntityInterface\\|false\\.$#" + count: 1 + path: src\Model\Behavior\PasswordBehavior.php + + - + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:findByUsernameOrEmail\\(\\)\\.$#" + count: 1 + path: src\Model\Behavior\PasswordBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$password\\.$#" + count: 1 + path: src\Model\Behavior\PasswordBehavior.php + + - + message: "#^Call to an undefined method Cake\\\\Datasource\\\\EntityInterface\\:\\:checkPassword\\(\\)\\.$#" + count: 1 + path: src\Model\Behavior\PasswordBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$password_confirm\\.$#" + count: 1 + path: src\Model\Behavior\PasswordBehavior.php + + - + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Behavior\\\\RegisterBehavior\\:\\:\\$validateEmail\\.$#" + count: 4 + path: src\Model\Behavior\RegisterBehavior.php + + - + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Behavior\\\\RegisterBehavior\\:\\:\\$useTos\\.$#" + count: 1 + path: src\Model\Behavior\RegisterBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$validated\\.$#" + count: 1 + path: src\Model\Behavior\RegisterBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$isValidateEmail\\.$#" + count: 1 + path: src\Model\Behavior\RegisterBehavior.php + + - + message: "#^Cannot call method tokenExpired\\(\\) on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" + count: 1 + path: src\Model\Behavior\RegisterBehavior.php + + - + message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\RegisterBehavior\\:\\:validate\\(\\) should return Cake\\\\Datasource\\\\EntityInterface but returns array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" + count: 1 + path: src\Model\Behavior\RegisterBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$active\\.$#" + count: 1 + path: src\Model\Behavior\RegisterBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$activation_date\\.$#" + count: 1 + path: src\Model\Behavior\RegisterBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$token_expires\\.$#" + count: 1 + path: src\Model\Behavior\RegisterBehavior.php + + - + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validationRegister\\(\\)\\.$#" + count: 1 + path: src\Model\Behavior\RegisterBehavior.php + + - + message: "#^Parameter \\#2 \\$user of method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:sendSocialValidationEmail\\(\\) expects Cake\\\\Datasource\\\\EntityInterface, array\\|Cake\\\\Datasource\\\\EntityInterface given\\.$#" + count: 1 + path: src\Model\Behavior\SocialAccountBehavior.php + + - + message: "#^Cannot access property \\$token on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" + count: 1 + path: src\Model\Behavior\SocialAccountBehavior.php + + - + message: "#^Cannot access property \\$active on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" + count: 2 + path: src\Model\Behavior\SocialAccountBehavior.php + + - + message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:validateAccount\\(\\) should return CakeDC\\\\Users\\\\Model\\\\Entity\\\\User but returns Cake\\\\Datasource\\\\EntityInterface\\.$#" + count: 1 + path: src\Model\Behavior\SocialAccountBehavior.php + + - + message: "#^Parameter \\#1 \\$socialAccount of method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:_activateAccount\\(\\) expects CakeDC\\\\Users\\\\Model\\\\Entity\\\\SocialAccount, array\\|Cake\\\\Datasource\\\\EntityInterface given\\.$#" + count: 1 + path: src\Model\Behavior\SocialAccountBehavior.php + + - + message: "#^Cannot access property \\$user on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" + count: 1 + path: src\Model\Behavior\SocialAccountBehavior.php + + - + message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:resendValidation\\(\\) should return CakeDC\\\\Users\\\\Model\\\\Entity\\\\User but returns array\\.$#" + count: 1 + path: src\Model\Behavior\SocialAccountBehavior.php + + - + message: "#^Parameter \\#1 \\$socialAccount of method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:sendSocialValidationEmail\\(\\) expects Cake\\\\Datasource\\\\EntityInterface, array\\|Cake\\\\Datasource\\\\EntityInterface given\\.$#" + count: 1 + path: src\Model\Behavior\SocialAccountBehavior.php + + - + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\SocialAccount\\:\\:\\$active\\.$#" + count: 1 + path: src\Model\Behavior\SocialAccountBehavior.php + + - + message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:_activateAccount\\(\\) should return Cake\\\\Datasource\\\\EntityInterface but returns Cake\\\\Datasource\\\\EntityInterface\\|false\\.$#" + count: 1 + path: src\Model\Behavior\SocialAccountBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$SocialAccounts\\.$#" + count: 4 + path: src\Model\Behavior\SocialBehavior.php + + - + message: "#^Parameter \\#2 \\$existingUser of method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialBehavior\\:\\:_populateUser\\(\\) expects Cake\\\\Datasource\\\\EntityInterface, array\\|Cake\\\\Datasource\\\\EntityInterface\\|null given\\.$#" + count: 1 + path: src\Model\Behavior\SocialBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$isValidateEmail\\.$#" + count: 1 + path: src\Model\Behavior\SocialBehavior.php + + - + message: "#^Parameter \\#3 \\$tokenExpiration of method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\BaseTokenBehavior\\:\\:_updateActive\\(\\) expects int, string given\\.$#" + count: 1 + path: src\Model\Behavior\SocialBehavior.php + + - + message: "#^PHPDoc tag @property has invalid value \\(\\\\Cake\\\\I18n\\\\Time token_expires\\)\\: Unexpected token \"token_expires\", expected TOKEN_VARIABLE at offset 167$#" + count: 1 + path: src\Model\Entity\User.php + + - + message: "#^PHPDoc tag @property has invalid value \\(array additional_data\\)\\: Unexpected token \"additional_data\", expected TOKEN_VARIABLE at offset 226$#" + count: 1 + path: src\Model\Entity\User.php + + - + message: "#^PHPDoc tag @property has invalid value \\(string token\\)\\: Unexpected token \"token\", expected TOKEN_VARIABLE at offset 201$#" + count: 1 + path: src\Model\Entity\User.php + + - + message: "#^Method CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\:\\:_setTos\\(\\) should return bool but returns string\\.$#" + count: 1 + path: src\Model\Entity\User.php + + - + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\:\\:\\$social_accounts\\.$#" + count: 1 + path: src\Model\Entity\User.php + + - + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\:\\:\\$additional_data\\.$#" + count: 1 + path: src\Model\Entity\User.php + + - + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\:\\:\\$token_expires\\.$#" + count: 1 + path: src\Model\Entity\User.php + + - + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\:\\:\\$token\\.$#" + count: 1 + path: src\Model\Entity\User.php + + - + message: "#^Property CakeDC\\\\Users\\\\Shell\\\\UsersShell\\:\\:\\$Users \\(CakeDC\\\\Users\\\\Model\\\\Table\\\\UsersTable\\) does not accept Cake\\\\Datasource\\\\RepositoryInterface\\.$#" + count: 1 + path: src\Shell\UsersShell.php + + - + message: "#^Cannot access property \\$role on bool\\|CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\.$#" + count: 1 + path: src\Shell\UsersShell.php + + - + message: "#^Cannot access property \\$username on bool\\.$#" + count: 2 + path: src\Shell\UsersShell.php + + - + message: "#^Call to an undefined method CakeDC\\\\Users\\\\Model\\\\Table\\\\UsersTable\\:\\:resetToken\\(\\)\\.$#" + count: 1 + path: src\Shell\UsersShell.php + + - + message: "#^Method CakeDC\\\\Users\\\\Shell\\\\UsersShell\\:\\:_changeUserActive\\(\\) should return bool but returns bool\\|CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\.$#" + count: 1 + path: src\Shell\UsersShell.php + + - + message: "#^Call to an undefined method CakeDC\\\\Users\\\\Model\\\\Table\\\\UsersTable\\:\\:generateUniqueUsername\\(\\)\\.$#" + count: 1 + path: src\Shell\UsersShell.php + + diff --git a/phpstan.neon b/phpstan.neon index 9b7e522fc..2f542b935 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,3 +1,6 @@ +includes: + - phpstan-baseline.neon + parameters: level: 7 autoload_files: diff --git a/psalm-baseline.xml b/psalm-baseline.xml new file mode 100644 index 000000000..305a69fbb --- /dev/null +++ b/psalm-baseline.xml @@ -0,0 +1,292 @@ + + + + + BaseController + + + + + getConfig + + + $checker + $checker + + + getConfig + + + + + AppController + + + + + public function resetOneTimePasswordAuthenticator($id = null) + + + + + \ReCaptcha\ReCaptcha + + + + + AppController + + + + + SocialIdentifier + + + + + $exception->getPrevious() + + + + + $exp + + + function ($exp) use ($identifier, $where) { + + + + + $result + + + \Cake\Datasource\EntityInterface + + + updateToken + + + + + $user->id + $socialAccount->user_id + $user->id + $user->social_accounts + $socialAccount->id + $user->social_accounts + + + $socialAccount + + + $accountData['avatar'] + + + + + $saveResult + + + string + + + $user->id + $user->current_password + $currentUser->password + $user->password_confirm + + + checkPassword + + + + + $user + + + $context + + + $user->validated + $user->active + $user->activation_date + $user->token_expires + $user->active + + + tokenExpired + + + $validateEmail + $tokenExpiration + + + tokenExpired + + + $this->_table->isValidateEmail + + + $this->validateEmail + $this->useTos + $this->validateEmail + + + $this->validateEmail + + + + + $result + + + $socialAccount + + + \Cake\Datasource\EntityInterface + + + $this->sendSocialValidationEmail($socialAccount, $socialAccount->user) + + + \CakeDC\Users\Model\Entity\User + + + $this->_activateAccount($socialAccount) + + + \CakeDC\Users\Model\Entity\User + + + $socialAccount->token + $socialAccount->active + $socialAccount->active + $socialAccount->user + + + $user + $socialAccount + + + + + $tokenExpiration + + + $existingAccount->user + + + $existingUser + + + $useEmail + $validateEmail + $tokenExpiration + $userData['username'] ?? null + $userData['username'] ?? null + $accountData['avatar'] + + + $userData + $userData + + + SocialBehavior + + + $this->_table->isValidateEmail + + + + + $tos + + + bool + + + + + SocialAccountsTable + + + + + \CakeDC\Users\Model\Entity\User|bool + + + UsersTable + + + + + Plugin + + + + + Shell + parent::getOptionParser() + parent::initialize() + + + $user->username + $user->username + + + $this->_updateUser($username, $data) + + + bool + + + $error + $field + $value + $field + $value + $field + + + $user->id + + + $savedUser->role + + + UsersShell + + + $this->Users + + + + + $title + + + AuthLinkHelper + + + + + $options['options'] + $options['options'] + + + + + $this->name + + + + + \Cake\Mailer\Mailer + + + + + $indexed + + + diff --git a/psalm.xml b/psalm.xml index bdbcdff1d..3bcbd74e4 100644 --- a/psalm.xml +++ b/psalm.xml @@ -5,6 +5,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" + errorBaseline="psalm-baseline.xml" > diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index 23cec8031..76fd358f0 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -125,7 +125,7 @@ public function getErrorMessage(?ResultInterface $result = null) * Determine redirect url after user identified * * @param array $user user data after identified - * @return \Cake\Http\Response + * @return \Cake\Http\Response|null */ protected function afterIdentifyUser($user) { From ef7fa221e94fcd9cdce66f01f2ff9b702e5a3c14 Mon Sep 17 00:00:00 2001 From: Rafael Queiroz Date: Sun, 1 Dec 2019 08:29:53 -0300 Subject: [PATCH 456/685] Pick config/users.php file by default if exists #508 --- config/bootstrap.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/bootstrap.php b/config/bootstrap.php index 27c05c01c..7fe26544b 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -15,6 +15,10 @@ use Cake\Routing\Router; Configure::load('CakeDC/Users.users'); +if (file_exists(CONFIG . 'users.php')) { + Configure::load('users'); +} + collection((array)Configure::read('Users.config'))->each(function ($file) { Configure::load($file); }); From f67fbd5ef2e97c2a04f765e7b3d32c039c62fb25 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Sat, 21 Dec 2019 19:50:45 +0300 Subject: [PATCH 457/685] release 9.0.0 --- .semver | 6 +++--- README.md | 3 ++- composer.json | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.semver b/.semver index 9999d2736..1c2a8edb2 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- -:major: 8 -:minor: 5 -:patch: 1 +:major: 9 +:minor: 0 +:patch: 0 :special: '' diff --git a/README.md b/README.md index 7d94e1e43..bc9f377fb 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ Versions and branches | :-------------: | :------------------------: | :--: | :---- | | 3.7 | [master](https://github.com/cakedc/users/tree/master) | 8.5.1 | stable | | 3.7 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | -| ^3.7 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | +| ^4.0 | [8.5](https://github.com/cakedc/users/tree/9.next) | 9.0.0 | stable | +| ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | | 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | | 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | | 3.4 | [5.x](https://github.com/cakedc/users/tree/5.x) | 5.2.0 | stable | diff --git a/composer.json b/composer.json index ac85a1902..7cd2a8736 100644 --- a/composer.json +++ b/composer.json @@ -29,10 +29,10 @@ "minimum-stability": "dev", "require": { "php": ">=7.2.0", - "cakephp/cakephp": "4.x-dev as 4.0.0", - "cakedc/auth": "feature/cakephp4-dev as 4.0.0", - "cakephp/authorization": "2.x-dev as 2.0", - "cakephp/authentication": "2.x-dev as 2.0" + "cakephp/cakephp": "^4.0.0", + "cakedc/auth": "^6.0.0", + "cakephp/authorization": "^2.0.0", + "cakephp/authentication": "^2.0.0" }, "require-dev": { "phpunit/phpunit": "^8.0", From accb5cfa390c9215b8669ff4b940da2f580a0e73 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 2 Jan 2020 10:49:43 -0300 Subject: [PATCH 458/685] Mapping users actions to /users/:action/* route and /social-accounts/:action/* --- config/routes.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/config/routes.php b/config/routes.php index f40b68263..192cc9287 100644 --- a/config/routes.php +++ b/config/routes.php @@ -14,11 +14,6 @@ use Cake\Core\Configure; use Cake\Routing\RouteBuilder; use CakeDC\Users\Utility\UsersUrl; -//Use custom path if url is customized -$baseUsersPath = UsersUrl::isCustom() ? '/users-base' : '/users'; -$routes->plugin('CakeDC/Users', ['path' => $baseUsersPath], function (RouteBuilder $routes) { - $routes->fallbacks('DashedRoute'); -}); $routes->connect('/accounts/validate/*', [ 'plugin' => 'CakeDC/Users', @@ -37,6 +32,8 @@ $routes->connect('/logout', UsersUrl::actionParams('logout')); $routes->connect('/link-social/*', UsersUrl::actionParams('linkSocial')); $routes->connect('/callback-link-social/*', UsersUrl::actionParams('callbackLinkSocial')); +$routes->connect('/register', UsersUrl::actionParams('register')); + $oauthPath = Configure::read('OAuth.path'); if (is_array($oauthPath)) { $routes->scope('/auth', function (RouteBuilder $routes) use ($oauthPath) { @@ -47,3 +44,9 @@ ); }); } + +$routes->connect('/social-accounts/:action/*', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'SocialAccounts', +]); +$routes->connect('/users/:action/*', UsersUrl::actionParams(null)); From c017b469b0855e37a3e47bc0880c9abfa1183867 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 2 Jan 2020 11:17:00 -0300 Subject: [PATCH 459/685] Updated template path --- Docs/Documentation/Configuration.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index c5f4081b7..34ca5dfeb 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -169,13 +169,15 @@ You need to configure 2 things: Configure::write('Auth.Identifiers', $identifiers); ``` -* 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 +* Override the login.php template to change the Form->control to "email". +Add (or copy from the [/templates/Users/login.php](../../templates/Users/login.php)) the file login.php to path /src/Template/Plugin/CakeDC/Users/Users/login.php +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 + // ... rest of your login.php code ``` @@ -187,24 +189,24 @@ 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/ +cp -r vendor/cakedc/users/templates/email/ templates/plugin/CakeDC/Users/email/ ``` -Then customize the email templates as you need under the src/Template/Plugin/CakeDC/Users/Email/ directory +Then customize the email templates as you need under the templates/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 +templates/plugin/CakeDC/Users/[Controller]/[view].php -Check http://book.cakephp.org/3.0/en/plugins.html#overriding-plugin-templates-from-inside-your-application +Check https://book.cakephp.org/4/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 +Check https://book.cakephp.org/4/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. From eadb051dbcb0ab24e9077b8c1fe7e70a368a3c4a Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 2 Jan 2020 11:26:23 -0300 Subject: [PATCH 460/685] Updated migration guide --- Docs/Documentation/Migration/8.x-9.0.md | 15 ++++++++++++++- Docs/Home.md | 3 +-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Docs/Documentation/Migration/8.x-9.0.md b/Docs/Documentation/Migration/8.x-9.0.md index b0f766412..7ae2a134c 100644 --- a/Docs/Documentation/Migration/8.x-9.0.md +++ b/Docs/Documentation/Migration/8.x-9.0.md @@ -1,7 +1,7 @@ Migration 8.x to 9.0 ====================== -9.0 uses the new plugins cakephp/authentication[(read more)](../Authentication.md) and cakephp/authorization[(read more)](../Authorization.md) instead of CakePHP +The 9.0 version uses the new plugins cakephp/authentication[(read more)](../Authentication.md) and cakephp/authorization[(read more)](../Authorization.md) instead of CakePHP Authentication component. This version is compatible with CakePHP 4.x and the plugin code was updated to remove all deprecations. @@ -98,3 +98,16 @@ Removed Events * `Users.Component.UsersAuth.failedSocialLogin` * `Users.Component.UsersAuth.afterCookieLogin` +Getting Authenticated User +-------------------------- + +In previous version you usually used AuthComponent to get the authenticated +user, now you should use the provided 'identity' attribute, you can do this +in your controller. + +``` +$user = $this->getRequest()->getAttribute('identity'); +if ($user) { + //Do stuff +} +``` diff --git a/Docs/Home.md b/Docs/Home.md index ebbbf4c73..5e493cb19 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -31,5 +31,4 @@ 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) - - +* [8.x to 9.0](Documentation/Migration/8.x-9.0.md) From 3c32cf0ad6af31f971e3f3de9cfd5416f021b4b7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 2 Jan 2020 11:34:50 -0300 Subject: [PATCH 461/685] Updated template path --- Docs/Documentation/Configuration.md | 2 +- Docs/Documentation/Extending-the-Plugin.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 34ca5dfeb..121127cb3 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -170,7 +170,7 @@ You need to configure 2 things: ``` * Override the login.php template to change the Form->control to "email". -Add (or copy from the [/templates/Users/login.php](../../templates/Users/login.php)) the file login.php to path /src/Template/Plugin/CakeDC/Users/Users/login.php +Add (or copy from the [/templates/Users/login.php](../../templates/Users/login.php)) the file login.php to path /templates/plugin/CakeDC/Users/Users/login.php and ensure it has the following content ```php diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index d7eb296c6..5c2d2f5f1 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -156,7 +156,7 @@ needed to setup correct url/route for authentication. // ... ``` -Note you'll need to **copy the Plugin templates** you need into your project src/Template/MyUsers/[action].ctp +Note you'll need to **copy the Plugin templates** you need into your project templates/MyUsers/[action].php You may also need to load some helpers in your AppView: @@ -205,9 +205,9 @@ 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 +https://book.cakephp.org/4/en/plugins.html#overriding-plugin-templates-from-inside-your-application -`{project_dir}/src/Template/Plugin/CakeDC/Users/Users/{templates_in_here}` +`{project_dir}/templates/plugin/CakeDC/Users/Users/{templates_in_here}` Updating the Emails ------------------- @@ -239,7 +239,7 @@ class MyUsersMailer extends UsersMailer * 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` +* Create the file `templates/email/text/custom_template_in_app_namespace.php` 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. From 6123a8a0edd2dd8cb7c558665aa7e39735267bf2 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 2 Jan 2020 11:36:35 -0300 Subject: [PATCH 462/685] Updated link to CakePHP documentation --- Docs/Documentation/Extending-the-Plugin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index 5c2d2f5f1..e205ac8df 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -7,7 +7,7 @@ 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 +match the colums using accessors & mutators as described here https://book.cakephp.org/4/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 From 64bf25414ca53f3559a0fbb2366a3459b79fb382 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 3 Jan 2020 12:38:31 -0500 Subject: [PATCH 463/685] Using entity for `$this->Form->create()` --- templates/Users/request_reset_password.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/templates/Users/request_reset_password.php b/templates/Users/request_reset_password.php index 5c6b2e18c..cda679691 100644 --- a/templates/Users/request_reset_password.php +++ b/templates/Users/request_reset_password.php @@ -1,6 +1,9 @@ +
Flash->render('auth') ?> - Form->create('User') ?> + Form->create(new User) ?>
Form->control('reference') ?> From e6b457b729bdbd916547f39bfcc34eef3f90cf77 Mon Sep 17 00:00:00 2001 From: Maxime Date: Wed, 8 Jan 2020 15:33:30 +0100 Subject: [PATCH 464/685] Add postLink method in AuthLinkHelper and add test on postlink with and without logged users --- src/View/Helper/AuthLinkHelper.php | 19 ++- .../View/Helper/AuthLinkHelperTest.php | 120 ++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index bf33ad2ad..cb66a52df 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -20,9 +20,10 @@ */ class AuthLinkHelper extends HtmlHelper { - use IsAuthorizedTrait; + public $helpers = ['Url', 'Form']; + /** * Generate a link if the target url is authorized for the logged in user * @@ -51,6 +52,22 @@ public function link($title, $url = null, array $options = []) return false; } + /** + * Wrapper for FormHelper.postLink. + * Write the link only if user is authorized. + * + * @param string $title Link's title + * @param [type] $url Link's url + * @param array $options Link's options + * @return string|bool Link as a string or false. + */ + public function postLink($title, $url = null, array $options = []) + { + return $this->isAuthorized($url) + ? $this->Form->postLink($title, $url, $options) + : false; + } + /** * Get the current request * diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php index a4e03c4bb..b1ecb64d8 100644 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -13,6 +13,8 @@ use CakeDC\Users\View\Helper\AuthLinkHelper; use Cake\Http\ServerRequest; +use Cake\ORM\TableRegistry; +use Cake\TestSuite\IntegrationTestTrait; use Cake\TestSuite\TestCase; use Cake\View\View; @@ -21,6 +23,16 @@ */ class AuthLinkHelperTest extends TestCase { + use IntegrationTestTrait; + + /** + * Fixtures + * + * @var array + */ + public $fixtures = [ + 'plugin.CakeDC/Users.Users', + ]; /** * Test subject @@ -130,4 +142,112 @@ public function testGetRequest() $actual = $this->AuthLink->getRequest(); $this->assertInstanceOf(ServerRequest::class, $actual); } + + /** + * Test post link with delete user method + * Logged as Super user + * + * @return void + */ + public function testPostLinkAuthorizedAllowedTrueLoggedAsAdmin() + { + $this->userTable = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->session( + [ + 'Auth' => [ + 'User' => $this->userTable->get('00000000-0000-0000-0000-000000000001'), + ], + ] + ); + $url = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'delete', + '00000000-0000-0000-0000-000000000010', + ]; + + $this->AuthLink->expects($this->once()) + ->method('isAuthorized') + ->with( + $this->equalTo($url) + ) + ->will($this->returnValue(true)); + + $link = $this->AuthLink->postLink('Post Link Title', $url, [ + 'allowed' => true, + 'class' => 'link-class', + 'confirm' => 'confirmation message', + ]); + + $this->assertContains('confirmation message', $link); + $this->assertContains('Post Link Title', $link); + } + + /** + * Test post link with delete user method + * Logged as normal user + * + * @return void + */ + public function testPostLinkAuthorizedAllowedFalseLoggedWithoutRole() + { + $this->userTable = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->session( + [ + 'Auth' => [ + 'User' => $this->userTable->get('00000000-0000-0000-0000-000000000004'), + ], + ] + ); + $url = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'delete', + '00000000-0000-0000-0000-000000000010', + ]; + + $this->AuthLink->expects($this->once()) + ->method('isAuthorized') + ->with( + $this->equalTo($url) + ) + ->will($this->returnValue(false)); + + $link = $this->AuthLink->postLink('Post Link Title', $url, [ + 'allowed' => true, + 'class' => 'link-class', + 'confirm' => 'confirmation message', + ]); + + $this->assertFalse($link); + } + + /** + * Test post link with delete user method + * + * @return void + */ + public function testPostLinkAuthorizedAllowedFalse() + { + $url = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'delete', + '00000000-0000-0000-0000-000000000010', + ]; + + $this->AuthLink->expects($this->once()) + ->method('isAuthorized') + ->with( + $this->equalTo($url) + ) + ->will($this->returnValue(false)); + + $link = $this->AuthLink->postLink('Post Link Title', $url, [ + 'allowed' => true, + 'class' => 'link-class', + 'confirm' => 'confirmation message', + ]); + $this->assertFalse($link); + } } From 5b59db0904638cda6b882bc6e5df20775d9c20df Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 9 Jan 2020 11:12:41 -0500 Subject: [PATCH 465/685] Add form create update to social_email.php --- templates/Users/social_email.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/templates/Users/social_email.php b/templates/Users/social_email.php index d0e3f68e2..1ceb627ca 100644 --- a/templates/Users/social_email.php +++ b/templates/Users/social_email.php @@ -8,10 +8,12 @@ * @copyright Copyright 2010 - 2018, Cake Development Corporation (https://www.cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ + +use CakeDC\Users\Model\Entity\User; ?>
Flash->render() ?> - Form->create('User') ?> + Form->create(new User) ?>
Form->control('email') ?> From 41a783cd18d52d56bc0920d32a8d0e4ad51cdf28 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Tue, 14 Jan 2020 15:10:37 +0300 Subject: [PATCH 466/685] don't load RequestAuthorizationMiddleware if it is ignored --- src/Loader/MiddlewareQueueLoader.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Loader/MiddlewareQueueLoader.php b/src/Loader/MiddlewareQueueLoader.php index 09e10ae26..4a89476a8 100644 --- a/src/Loader/MiddlewareQueueLoader.php +++ b/src/Loader/MiddlewareQueueLoader.php @@ -115,7 +115,11 @@ protected function loadAuthorizationMiddleware(MiddlewareQueue $middlewareQueue, } $middlewareQueue->add(new AuthorizationMiddleware($plugin, Configure::read('Auth.AuthorizationMiddleware'))); - $middlewareQueue->add(new RequestAuthorizationMiddleware()); + + if (Configure::read('Auth.AuthorizationMiddleware.requireAuthorizationCheck') !== false) { + $middlewareQueue->add(new RequestAuthorizationMiddleware()); + } + return $middlewareQueue; } From a463a273869e15016d4dddc9c904b6ee55304238 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 14 Jan 2020 09:26:56 -0300 Subject: [PATCH 467/685] Fixed FormHelper::create calls --- templates/Users/request_reset_password.php | 5 +---- templates/Users/social_email.php | 6 ++---- templates/Users/u2f_authenticate.php | 2 +- templates/Users/u2f_register.php | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/templates/Users/request_reset_password.php b/templates/Users/request_reset_password.php index cda679691..ccd7c4264 100644 --- a/templates/Users/request_reset_password.php +++ b/templates/Users/request_reset_password.php @@ -1,9 +1,6 @@ -
Flash->render('auth') ?> - Form->create(new User) ?> + Form->create($user) ?>
Form->control('reference') ?> diff --git a/templates/Users/social_email.php b/templates/Users/social_email.php index 1ceb627ca..55c1208e9 100644 --- a/templates/Users/social_email.php +++ b/templates/Users/social_email.php @@ -8,15 +8,13 @@ * @copyright Copyright 2010 - 2018, Cake Development Corporation (https://www.cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ - -use CakeDC\Users\Model\Entity\User; ?>
Flash->render() ?> - Form->create(new User) ?> + Form->create() ?>
- Form->control('email') ?> + Form->control('email', ['type' => 'email', 'required' => true]) ?>
Form->button(__d('cake_d_c/users', 'Submit')); ?> Form->end() ?> diff --git a/templates/Users/u2f_authenticate.php b/templates/Users/u2f_authenticate.php index 0ec64aaa8..5b48555de 100644 --- a/templates/Users/u2f_authenticate.php +++ b/templates/Users/u2f_authenticate.php @@ -8,7 +8,7 @@
- Form->create(false, [ + Form->create(null, [ 'url' => [ 'action' => 'u2fAuthenticateFinish', '?' => $this->request->getQueryParams() diff --git a/templates/Users/u2f_register.php b/templates/Users/u2f_register.php index 244505873..0ea8da5af 100644 --- a/templates/Users/u2f_register.php +++ b/templates/Users/u2f_register.php @@ -8,7 +8,7 @@
- Form->create(false, [ + Form->create(null, [ 'url' => [ 'action' => 'u2fRegisterFinish', '?' => $this->request->getQueryParams() From a0c9a492c347493e8b57b5d487f9403e6788e5d6 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 14 Jan 2020 09:44:03 -0300 Subject: [PATCH 468/685] phpcs fixes --- src/Loader/MiddlewareQueueLoader.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Loader/MiddlewareQueueLoader.php b/src/Loader/MiddlewareQueueLoader.php index 4a89476a8..a1f4cca97 100644 --- a/src/Loader/MiddlewareQueueLoader.php +++ b/src/Loader/MiddlewareQueueLoader.php @@ -113,14 +113,11 @@ protected function loadAuthorizationMiddleware(MiddlewareQueue $middlewareQueue, if (Configure::read('Auth.Authorization.enable') === false) { return $middlewareQueue; } - $middlewareQueue->add(new AuthorizationMiddleware($plugin, Configure::read('Auth.AuthorizationMiddleware'))); - if (Configure::read('Auth.AuthorizationMiddleware.requireAuthorizationCheck') !== false) { $middlewareQueue->add(new RequestAuthorizationMiddleware()); } - return $middlewareQueue; } } From 52648b34640cc165d53f5d79b1545830e3385871 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 14 Jan 2020 12:12:27 -0300 Subject: [PATCH 469/685] Fixin --- composer.json | 8 +- config/routes.php | 18 ++-- src/Utility/UsersUrl.php | 10 +++ tests/TestCase/Utility/UsersUrlTest.php | 105 +++++++++++++++++++++++- 4 files changed, 126 insertions(+), 15 deletions(-) diff --git a/composer.json b/composer.json index 7cd2a8736..206dac8bd 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,8 @@ "cakephp/cakephp": "^4.0.0", "cakedc/auth": "^6.0.0", "cakephp/authorization": "^2.0.0", - "cakephp/authentication": "^2.0.0" + "cakephp/authentication": "^2.0.0", + "cakephp/cakephp-codesniffer": "dev-master" }, "require-dev": { "phpunit/phpunit": "^8.0", @@ -45,8 +46,7 @@ "robthree/twofactorauth": "^1.6", "yubico/u2flib-server": "^1.0", "php-coveralls/php-coveralls": "^2.1", - "league/oauth1-client": "^1.7", - "cakephp/cakephp-codesniffer": "dev-next" + "league/oauth1-client": "^1.7" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", @@ -89,7 +89,7 @@ "stan-rebuild-baseline": "phpstan analyse --configuration phpstan.neon --error-format baselineNeon src/ > phpstan-baseline.neon", "psalm-rebuild-baseline": "php vendor/psalm/phar/psalm.phar --show-info=false --set-baseline=psalm-baseline.xml src/", "rector": "rector process src/", - "rector-setup": "cp composer.json composer.backup && composer require --dev rector/rector:^0.4.11 && mv composer.backup composer.json", + "rector-setup": "cp composer.json composer.backup && composer require --dev rector/rector:^0.4.11 && mv composer.backup composer.json", "coverage-test": "phpunit --stderr --coverage-clover=clover.xml" } } diff --git a/config/routes.php b/config/routes.php index 192cc9287..023c99f7d 100644 --- a/config/routes.php +++ b/config/routes.php @@ -22,17 +22,17 @@ ]); // Google Authenticator related routes if (Configure::read('OneTimePasswordAuthenticator.login')) { - $routes->connect('/verify', UsersUrl::actionParams('verify')); + $routes->connect('/verify', UsersUrl::actionRouteParams('verify')); - $routes->connect('/resetOneTimePasswordAuthenticator', UsersUrl::actionParams('resetOneTimePasswordAuthenticator')); + $routes->connect('/resetOneTimePasswordAuthenticator', UsersUrl::actionRouteParams('resetOneTimePasswordAuthenticator')); } -$routes->connect('/profile/*', UsersUrl::actionParams('profile')); -$routes->connect('/login', UsersUrl::actionParams('login')); -$routes->connect('/logout', UsersUrl::actionParams('logout')); -$routes->connect('/link-social/*', UsersUrl::actionParams('linkSocial')); -$routes->connect('/callback-link-social/*', UsersUrl::actionParams('callbackLinkSocial')); -$routes->connect('/register', UsersUrl::actionParams('register')); +$routes->connect('/profile/*', UsersUrl::actionRouteParams('profile')); +$routes->connect('/login', UsersUrl::actionRouteParams('login')); +$routes->connect('/logout', UsersUrl::actionRouteParams('logout')); +$routes->connect('/link-social/*', UsersUrl::actionRouteParams('linkSocial')); +$routes->connect('/callback-link-social/*', UsersUrl::actionRouteParams('callbackLinkSocial')); +$routes->connect('/register', UsersUrl::actionRouteParams('register')); $oauthPath = Configure::read('OAuth.path'); if (is_array($oauthPath)) { @@ -49,4 +49,4 @@ 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', ]); -$routes->connect('/users/:action/*', UsersUrl::actionParams(null)); +$routes->connect('/users/:action/*', UsersUrl::actionRouteParams(null)); diff --git a/src/Utility/UsersUrl.php b/src/Utility/UsersUrl.php index 19c0d713f..a1d0a7ef5 100644 --- a/src/Utility/UsersUrl.php +++ b/src/Utility/UsersUrl.php @@ -46,6 +46,16 @@ public static function actionUrl($action, $extra = []) return $params + $extra; } + /** + * Get an user action route. This should not be user for links like HtmlHelper::link + * + * @param string $action user action + * @return array + */ + public static function actionRouteParams($action) + { + return array_filter(static::actionParams($action)); + } /** * Get an user action route. This should not be user for links like HtmlHelper::link diff --git a/tests/TestCase/Utility/UsersUrlTest.php b/tests/TestCase/Utility/UsersUrlTest.php index 0fa167766..2134a55ce 100644 --- a/tests/TestCase/Utility/UsersUrlTest.php +++ b/tests/TestCase/Utility/UsersUrlTest.php @@ -26,7 +26,108 @@ class UsersUrlTest extends TestCase * * @return array */ - public function dataProviderActionRoute() + public function dataProviderActionRouteParams() + { + return [ + ['verify', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify'], null], + ['linkSocial', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'linkSocial'], null], + ['callbackLinkSocial', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'callbackLinkSocial'], null], + ['socialLogin', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialLogin'], null], + ['login', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login'], null], + ['logout', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout'], null], + ['getUsersTable', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'getUsersTable'], null], + ['setUsersTable', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'setUsersTable'], null], + ['profile', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile'], null], + ['validateReCaptcha', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateReCaptcha'], null], + ['register', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'register'], null], + ['validateEmail', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail'], null], + ['changePassword', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'changePassword'], null], + ['resetPassword', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetPassword'], null], + ['requestResetPassword', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'requestResetPassword'], null], + ['resetOneTimePasswordAuthenticator', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resetOneTimePasswordAuthenticator'], null], + ['validate', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validate'], null], + ['resendTokenValidation', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'resendTokenValidation'], null], + ['index', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'index'], null], + ['view', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'view'], null], + ['add', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'add'], null], + ['edit', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'edit'], null], + ['delete', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'delete'], null], + ['socialEmail', ['plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail'], null], + + ['verify', ['controller' => 'Users', 'action' => 'verify'], 'Users'], + ['linkSocial', ['controller' => 'Users', 'action' => 'linkSocial'], 'Users'], + ['callbackLinkSocial', ['controller' => 'Users', 'action' => 'callbackLinkSocial'], 'Users'], + ['socialLogin', ['controller' => 'Users', 'action' => 'socialLogin'], 'Users'], + ['login', ['controller' => 'Users', 'action' => 'login'], 'Users'], + ['logout', ['controller' => 'Users', 'action' => 'logout'], 'Users'], + ['getUsersTable', ['controller' => 'Users', 'action' => 'getUsersTable'], 'Users'], + ['setUsersTable', ['controller' => 'Users', 'action' => 'setUsersTable'], 'Users'], + ['profile', ['controller' => 'Users', 'action' => 'profile'], 'Users'], + ['validateReCaptcha', ['controller' => 'Users', 'action' => 'validateReCaptcha'], 'Users'], + ['register', ['controller' => 'Users', 'action' => 'register'], 'Users'], + ['validateEmail', ['controller' => 'Users', 'action' => 'validateEmail'], 'Users'], + ['changePassword', ['controller' => 'Users', 'action' => 'changePassword'], 'Users'], + ['resetPassword', ['controller' => 'Users', 'action' => 'resetPassword'], 'Users'], + ['requestResetPassword', ['controller' => 'Users', 'action' => 'requestResetPassword'], 'Users'], + ['resetOneTimePasswordAuthenticator', ['controller' => 'Users', 'action' => 'resetOneTimePasswordAuthenticator'], 'Users'], + ['validate', ['controller' => 'Users', 'action' => 'validate'], 'Users'], + ['resendTokenValidation', ['controller' => 'Users', 'action' => 'resendTokenValidation'], 'Users'], + ['index', ['controller' => 'Users', 'action' => 'index'], 'Users'], + ['view', ['controller' => 'Users', 'action' => 'view'], 'Users'], + ['add', ['controller' => 'Users', 'action' => 'add'], 'Users'], + ['edit', ['controller' => 'Users', 'action' => 'edit'], 'Users'], + ['delete', ['controller' => 'Users', 'action' => 'delete'], 'Users'], + ['socialEmail', ['controller' => 'Users', 'action' => 'socialEmail'], 'Users'], + + ['verify', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'verify'], 'Admin/Users'], + ['linkSocial', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'linkSocial'], 'Admin/Users'], + ['callbackLinkSocial', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'callbackLinkSocial'], 'Admin/Users'], + ['socialLogin', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'socialLogin'], 'Admin/Users'], + ['login', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'login'], 'Admin/Users'], + ['logout', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'logout'], 'Admin/Users'], + ['getUsersTable', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'getUsersTable'], 'Admin/Users'], + ['setUsersTable', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'setUsersTable'], 'Admin/Users'], + ['profile', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'profile'], 'Admin/Users'], + ['validateReCaptcha', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'validateReCaptcha'], 'Admin/Users'], + ['register', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'register'], 'Admin/Users'], + ['validateEmail', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'validateEmail'], 'Admin/Users'], + ['changePassword', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'changePassword'], 'Admin/Users'], + ['resetPassword', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'resetPassword'], 'Admin/Users'], + ['requestResetPassword', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'requestResetPassword'], 'Admin/Users'], + ['resetOneTimePasswordAuthenticator', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'resetOneTimePasswordAuthenticator'], 'Admin/Users'], + ['validate', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'validate'], 'Admin/Users'], + ['resendTokenValidation', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'resendTokenValidation'], 'Admin/Users'], + ['index', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'index'], 'Admin/Users'], + ['view', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'view'], 'Admin/Users'], + ['add', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'add'], 'Admin/Users'], + ['edit', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'edit'], 'Admin/Users'], + ['delete', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'delete'], 'Admin/Users'], + ['socialEmail', ['prefix' => 'Admin', 'controller' => 'Users', 'action' => 'socialEmail'], 'Admin/Users'], + ]; + } + + /** + * Test actionRouteParams method + * + * @dataProvider dataProviderActionRouteParams + * @param string $action user action. + * @param array $expected expected url + * @param string $controller controller name for users, optional + * @return void + */ + public function testActionRouteParams($action, $expected, $controller = null) + { + Configure::write('Users.controller', $controller); + $actual = UsersUrl::actionRouteParams($action); + $this->assertSame($expected, $actual); + } + + /** + * Data provider for test testActionParams + * + * @return array + */ + public function dataProviderActionParams() { return [ ['verify', ['prefix' => null, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'verify'], null], @@ -109,7 +210,7 @@ public function dataProviderActionRoute() /** * Test actionParams method * - * @dataProvider dataProviderActionRoute + * @dataProvider dataProviderActionParams * @param string $action user action. * @param array $expected expected url * @param string $controller controller name for users, optional From 5b9345bdf8d68aef42cd7c13c86ce994471bacd3 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 14 Jan 2020 12:14:39 -0300 Subject: [PATCH 470/685] phpcs fixes --- src/Utility/UsersUrl.php | 1 + tests/TestCase/PluginTest.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Utility/UsersUrl.php b/src/Utility/UsersUrl.php index a1d0a7ef5..fcce64c7b 100644 --- a/src/Utility/UsersUrl.php +++ b/src/Utility/UsersUrl.php @@ -46,6 +46,7 @@ public static function actionUrl($action, $extra = []) return $params + $extra; } + /** * Get an user action route. This should not be user for links like HtmlHelper::link * diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 8b1ad30e7..befaaa762 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -320,7 +320,7 @@ public function testGetAuthenticationService() $this->assertEquals($expected, $actual); /** - * @var \Authentication\Authenticator\AuthenticatorCollection $authenticators + * @var \Authentication\Identifier\IdentifierCollection $identifiers */ $identifiers = $service->identifiers(); $expected = [ From e7f90c5630abcf2b171f49515d7ab2c4d61959ed Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 14 Jan 2020 12:19:58 -0300 Subject: [PATCH 471/685] Template using configured user url --- templates/email/html/reset_password.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/templates/email/html/reset_password.php b/templates/email/html/reset_password.php index 36c3e11cc..250b63f41 100644 --- a/templates/email/html/reset_password.php +++ b/templates/email/html/reset_password.php @@ -9,14 +9,10 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -$activationUrl = [ +$activationUrl = \CakeDC\Users\Utility\UsersUrl::actionUrl('resetPassword', [ '_full' => true, - 'prefix' => false, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'resetPassword', isset($token) ? $token : '' -]; +]); ?>

, From c2cc195e827b4f09182186f1c1f156c60bd67a2e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 31 Oct 2019 08:25:03 -0300 Subject: [PATCH 472/685] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index bc9f377fb..8f051ee72 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,12 @@ CakeDC Users Plugin [![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) +Warning +------- + +**OUTDATED branch, please use the specific develop branch for each version, for example 8.x for the version 8 development** + + Versions and branches --------------------- From ee86bafdbb0bf15321acbddab1814685c5b735ad Mon Sep 17 00:00:00 2001 From: Maxime Date: Wed, 8 Jan 2020 15:33:30 +0100 Subject: [PATCH 473/685] Add postLink method in AuthLinkHelper and add test on postlink with and without logged users --- src/View/Helper/AuthLinkHelper.php | 18 +++ .../View/Helper/AuthLinkHelperTest.php | 110 ++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index 38ad0b175..bc4fd6f86 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -23,6 +23,8 @@ class AuthLinkHelper extends HtmlHelper { use IsAuthorizedTrait; + public $helpers = ['Url', 'Form']; + /** * Generate a link if the target url is authorized for the logged in user * @@ -51,6 +53,22 @@ public function link($title, $url = null, array $options = []): string return ''; } + /** + * Wrapper for FormHelper.postLink. + * Write the link only if user is authorized. + * + * @param string $title Link's title + * @param [type] $url Link's url + * @param array $options Link's options + * @return string|bool Link as a string or false. + */ + public function postLink($title, $url = null, array $options = []) + { + return $this->isAuthorized($url) + ? $this->Form->postLink($title, $url, $options) + : false; + } + /** * Get the current request * diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php index ab4f8e805..30121bb37 100644 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -15,6 +15,8 @@ use Cake\Http\ServerRequest; use Cake\Routing\Router; +use Cake\ORM\TableRegistry; +use Cake\TestSuite\IntegrationTestTrait; use Cake\TestSuite\TestCase; use Cake\View\View; use CakeDC\Users\View\Helper\AuthLinkHelper; @@ -137,4 +139,112 @@ public function testGetRequest() $actual = $this->AuthLink->getRequest(); $this->assertInstanceOf(ServerRequest::class, $actual); } + + /** + * Test post link with delete user method + * Logged as Super user + * + * @return void + */ + public function testPostLinkAuthorizedAllowedTrueLoggedAsAdmin() + { + $this->userTable = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->session( + [ + 'Auth' => [ + 'User' => $this->userTable->get('00000000-0000-0000-0000-000000000001'), + ], + ] + ); + $url = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'delete', + '00000000-0000-0000-0000-000000000010', + ]; + + $this->AuthLink->expects($this->once()) + ->method('isAuthorized') + ->with( + $this->equalTo($url) + ) + ->will($this->returnValue(true)); + + $link = $this->AuthLink->postLink('Post Link Title', $url, [ + 'allowed' => true, + 'class' => 'link-class', + 'confirm' => 'confirmation message', + ]); + + $this->assertContains('confirmation message', $link); + $this->assertContains('Post Link Title', $link); + } + + /** + * Test post link with delete user method + * Logged as normal user + * + * @return void + */ + public function testPostLinkAuthorizedAllowedFalseLoggedWithoutRole() + { + $this->userTable = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->session( + [ + 'Auth' => [ + 'User' => $this->userTable->get('00000000-0000-0000-0000-000000000004'), + ], + ] + ); + $url = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'delete', + '00000000-0000-0000-0000-000000000010', + ]; + + $this->AuthLink->expects($this->once()) + ->method('isAuthorized') + ->with( + $this->equalTo($url) + ) + ->will($this->returnValue(false)); + + $link = $this->AuthLink->postLink('Post Link Title', $url, [ + 'allowed' => true, + 'class' => 'link-class', + 'confirm' => 'confirmation message', + ]); + + $this->assertFalse($link); + } + + /** + * Test post link with delete user method + * + * @return void + */ + public function testPostLinkAuthorizedAllowedFalse() + { + $url = [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'delete', + '00000000-0000-0000-0000-000000000010', + ]; + + $this->AuthLink->expects($this->once()) + ->method('isAuthorized') + ->with( + $this->equalTo($url) + ) + ->will($this->returnValue(false)); + + $link = $this->AuthLink->postLink('Post Link Title', $url, [ + 'allowed' => true, + 'class' => 'link-class', + 'confirm' => 'confirmation message', + ]); + $this->assertFalse($link); + } } From bd3a6c2a08d3fc5785d938f1fda0da3e601a0029 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 15 Jan 2020 17:19:17 -0300 Subject: [PATCH 474/685] Reset password e-mail as html and text. Code cleanup --- templates/email/html/reset_password.php | 4 --- templates/email/text/reset_password.php | 9 ----- tests/TestCase/Mailer/UsersMailerTest.php | 42 ++++++++++++++--------- 3 files changed, 26 insertions(+), 29 deletions(-) diff --git a/templates/email/html/reset_password.php b/templates/email/html/reset_password.php index 250b63f41..4009e9134 100644 --- a/templates/email/html/reset_password.php +++ b/templates/email/html/reset_password.php @@ -9,10 +9,6 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -$activationUrl = \CakeDC\Users\Utility\UsersUrl::actionUrl('resetPassword', [ - '_full' => true, - isset($token) ? $token : '' -]); ?>

, diff --git a/templates/email/text/reset_password.php b/templates/email/text/reset_password.php index ddf3feea8..312ac428d 100644 --- a/templates/email/text/reset_password.php +++ b/templates/email/text/reset_password.php @@ -8,15 +8,6 @@ * @copyright Copyright 2010 - 2018, Cake Development Corporation (https://www.cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ - -$activationUrl = [ - '_full' => true, - 'prefix' => false, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'resetPassword', - isset($token) ? $token : '' -]; ?> , diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index 76652511d..6787bcd32 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -12,8 +12,10 @@ */ namespace CakeDC\Users\Test\TestCase\Email; +use Cake\Mailer\Message; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; +use CakeDC\Users\Mailer\UsersMailer; /** * Test Case @@ -29,6 +31,10 @@ class UsersMailerTest extends TestCase 'plugin.CakeDC/Users.SocialAccounts', 'plugin.CakeDC/Users.Users', ]; + /** + * @var UsersMailer + */ + private $UsersMailer; /** * setUp @@ -127,29 +133,33 @@ public function testSocialAccountValidation() */ public function testResetPassword() { + $this->UsersMailer = new UsersMailer(); $table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $data = [ + $user = $table->newEntity([ + 'first_name' => 'FirstName', + 'email' => 'test@example.com', + 'token' => '12345', + ]); + $expectedViewVars = [ + 'activationUrl' => [ + 'prefix' => false, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'resetPassword', + '_full' => true, + '12345' + ], 'first_name' => 'FirstName', 'email' => 'test@example.com', 'token' => '12345', ]; - $user = $table->newEntity($data); - $this->Email->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->UsersMailer->expects($this->once()) - ->method('setViewVars') - ->with($data) - ->will($this->returnValue($this->UsersMailer)); $this->invokeMethod($this->UsersMailer, 'resetPassword', [$user]); + $this->assertSame(['test@example.com' => 'test@example.com'], $this->UsersMailer->getTo()); + $this->assertSame('FirstName, Your reset password link', $this->UsersMailer->getSubject()); + $this->assertSame(Message::MESSAGE_BOTH, $this->UsersMailer->getEmailFormat()); + $this->assertSame($expectedViewVars, $this->UsersMailer->viewBuilder()->getVars()); + $this->assertSame('CakeDC/Users.resetPassword', $this->UsersMailer->viewBuilder()->getTemplate()); } /** From 1ae4b894af4ff905ebd36ae21e676ad832545d4d Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 15 Jan 2020 17:32:09 -0300 Subject: [PATCH 475/685] e-mail 'validate account' as html and text. Moved link to mailer. Code cleanup --- templates/email/html/validation.php | 9 ----- templates/email/text/validation.php | 9 ----- tests/TestCase/Mailer/UsersMailerTest.php | 40 +++++++++++++---------- 3 files changed, 23 insertions(+), 35 deletions(-) diff --git a/templates/email/html/validation.php b/templates/email/html/validation.php index 8b3ce9fb4..ad92d2f3e 100644 --- a/templates/email/html/validation.php +++ b/templates/email/html/validation.php @@ -8,15 +8,6 @@ * @copyright Copyright 2010 - 2018, Cake Development Corporation (https://www.cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ - -$activationUrl = [ - '_full' => true, - 'prefix' => false, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'validateEmail', - isset($token) ? $token : '' -]; ?>

, diff --git a/templates/email/text/validation.php b/templates/email/text/validation.php index 2b2b78cc3..312ac428d 100644 --- a/templates/email/text/validation.php +++ b/templates/email/text/validation.php @@ -8,15 +8,6 @@ * @copyright Copyright 2010 - 2018, Cake Development Corporation (https://www.cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ - -$activationUrl = [ - '_full' => true, - 'prefix' => false, - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'validateEmail', - isset($token) ? $token : '' -]; ?> , diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index 6787bcd32..7c714e46a 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -73,29 +73,35 @@ public function tearDown(): void */ public function testValidation() { + $this->UsersMailer = new UsersMailer(); $table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $data = [ + $expectedViewVars = [ + 'activationUrl' => [ + 'prefix' => false, + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'validateEmail', + '_full' => true, + '12345678' + ], 'first_name' => 'FirstName', + 'last_name' => 'Bond', 'email' => 'test@example.com', - 'token' => '12345', + 'token' => '12345678', ]; - $user = $table->newEntity($data); - $this->Email->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->UsersMailer->expects($this->once()) - ->method('setViewVars') - ->with($data) - ->will($this->returnValue($this->UsersMailer)); + $user = $table->newEntity([ + 'first_name' => 'FirstName', + 'last_name' => 'Bond', + 'email' => 'test@example.com', + 'token' => '12345678', + ]); $this->invokeMethod($this->UsersMailer, 'validation', [$user]); + $this->assertSame(['test@example.com' => 'test@example.com'], $this->UsersMailer->getTo()); + $this->assertSame('FirstName, Your account validation link', $this->UsersMailer->getSubject()); + $this->assertSame(Message::MESSAGE_BOTH, $this->UsersMailer->getEmailFormat()); + $this->assertSame($expectedViewVars, $this->UsersMailer->viewBuilder()->getVars()); + $this->assertSame('CakeDC/Users.validation', $this->UsersMailer->viewBuilder()->getTemplate()); } /** From 06be36fe654a4a24abd6d895e30ecfec5a84f989 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 15 Jan 2020 17:46:51 -0300 Subject: [PATCH 476/685] e-mail message as html and text. Moved link to mailer. Code cleanup --- .../email/html/social_account_validation.php | 10 ---- .../email/text/social_account_validation.php | 11 ----- tests/TestCase/Mailer/UsersMailerTest.php | 48 +++++++++---------- 3 files changed, 22 insertions(+), 47 deletions(-) diff --git a/templates/email/html/social_account_validation.php b/templates/email/html/social_account_validation.php index fde01878c..01d2fab85 100644 --- a/templates/email/html/social_account_validation.php +++ b/templates/email/html/social_account_validation.php @@ -16,16 +16,6 @@

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

diff --git a/templates/email/text/social_account_validation.php b/templates/email/text/social_account_validation.php index 7e3d5e5e4..79dc496de 100644 --- a/templates/email/text/social_account_validation.php +++ b/templates/email/text/social_account_validation.php @@ -8,17 +8,6 @@ * @copyright Copyright 2010 - 2018, Cake Development Corporation (https://www.cakedc.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ - -$activationUrl = [ - '_full' => true, - 'prefix' => false, - 'plugin' => 'CakeDC/Users', - 'controller' => 'SocialAccounts', - 'action' => 'validateAccount', - $socialAccount['provider'], - $socialAccount['reference'], - $socialAccount['token'], -]; ?> , diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index 7c714e46a..0755d4bb4 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -16,6 +16,7 @@ use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use CakeDC\Users\Mailer\UsersMailer; +use CakeDC\Users\Model\Entity\User; /** * Test Case @@ -43,15 +44,8 @@ class UsersMailerTest extends TestCase */ public function setUp(): void { + $this->UsersMailer = new UsersMailer(); parent::setUp(); - $this->Email = $this->getMockBuilder('Cake\Mailer\Message') - ->setMethods(['setTo', 'setSubject', 'setViewVars', 'setTemplate']) - ->getMock(); - - $this->UsersMailer = $this->getMockBuilder('CakeDC\Users\Mailer\UsersMailer') - ->setMethods(['setViewVars']) - ->getMock(); - $this->UsersMailer->setMessage($this->Email); } /** @@ -62,7 +56,6 @@ public function setUp(): void public function tearDown(): void { unset($this->UsersMailer); - unset($this->Email); parent::tearDown(); } @@ -73,7 +66,6 @@ public function tearDown(): void */ public function testValidation() { - $this->UsersMailer = new UsersMailer(); $table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $expectedViewVars = [ 'activationUrl' => [ @@ -113,23 +105,28 @@ public function testSocialAccountValidation() { $social = TableRegistry::getTableLocator()->get('CakeDC/Users.SocialAccounts') ->get('00000000-0000-0000-0000-000000000001', ['contain' => 'Users']); - - $this->Email->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->UsersMailer->expects($this->once()) - ->method('setViewVars') - ->with(['user' => $social->user, 'socialAccount' => $social]) - ->will($this->returnValue($this->UsersMailer)); + $this->assertInstanceOf(User::class, $social->user); + $expectedViewVars = [ + 'user' => $social->user, + 'socialAccount' => $social, + 'activationUrl' => [ + '_full' => true, + 'prefix' => false, + 'plugin' => 'CakeDC/Users', + 'controller' => 'SocialAccounts', + 'action' => 'validateAccount', + 'Facebook', + 'reference-1-1234', + 'token-1234' + ], + ]; $this->invokeMethod($this->UsersMailer, 'socialAccountValidation', [$social->user, $social]); + $this->assertSame(['user-1@test.com' => 'user-1@test.com'], $this->UsersMailer->getTo()); + $this->assertSame('first1, Your social account validation link', $this->UsersMailer->getSubject()); + $this->assertSame(Message::MESSAGE_BOTH, $this->UsersMailer->getEmailFormat()); + $this->assertSame($expectedViewVars, $this->UsersMailer->viewBuilder()->getVars()); + $this->assertSame('CakeDC/Users.socialAccountValidation', $this->UsersMailer->viewBuilder()->getTemplate()); } /** @@ -139,7 +136,6 @@ public function testSocialAccountValidation() */ public function testResetPassword() { - $this->UsersMailer = new UsersMailer(); $table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $user = $table->newEntity([ 'first_name' => 'FirstName', From d22115a59726ac01f53ab5d90f32bf3e2facb0df Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 15 Jan 2020 17:48:05 -0300 Subject: [PATCH 477/685] e-mail messages as html and text. Moved link to mailer. Code cleanup --- src/Mailer/UsersMailer.php | 39 ++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 4140211b7..fb0e1aebc 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -14,6 +14,8 @@ use Cake\Datasource\EntityInterface; use Cake\Mailer\Mailer; +use Cake\Mailer\Message; +use CakeDC\Users\Utility\UsersUrl; /** * User Mailer @@ -33,11 +35,21 @@ protected function validation(EntityInterface $user) // un-hide the token to be able to send it in the email content $user->setHidden(['password', 'token_expires', 'api_token']); $subject = __d('cake_d_c/users', 'Your account validation link'); + $viewVars = [ + 'activationUrl' => UsersUrl::actionUrl('validateEmail', [ + '_full' => true, + $user->token + ]), + ] + $user->toArray(); + $this ->setTo($user['email']) ->setSubject($firstName . $subject) - ->setViewVars($user->toArray()) - ->viewBuilder()->setTemplate('CakeDC/Users.validation'); + ->setEmailFormat(Message::MESSAGE_BOTH) + ->setViewVars($viewVars); + + $this->viewBuilder() + ->setTemplate('CakeDC/Users.validation'); } /** @@ -54,10 +66,18 @@ protected function resetPassword(EntityInterface $user) // un-hide the token to be able to send it in the email content $user->setHidden(['password', 'token_expires', 'api_token']); + $viewVars = [ + 'activationUrl' => UsersUrl::actionUrl('resetPassword', [ + '_full' => true, + $user->token + ]), + ] + $user->toArray(); + $this ->setTo($user['email']) ->setSubject($subject) - ->setViewVars($user->toArray()); + ->setEmailFormat(Message::MESSAGE_BOTH) + ->setViewVars($viewVars); $this ->viewBuilder() ->setTemplate('CakeDC/Users.resetPassword'); @@ -76,10 +96,21 @@ protected function socialAccountValidation(EntityInterface $user, EntityInterfac $firstName = isset($user['first_name']) ? $user['first_name'] . ', ' : ''; // note: we control the space after the username in the previous line $subject = __d('cake_d_c/users', '{0}Your social account validation link', $firstName); + $activationUrl = [ + '_full' => true, + 'prefix' => false, + 'plugin' => 'CakeDC/Users', + 'controller' => 'SocialAccounts', + 'action' => 'validateAccount', + $socialAccount['provider'], + $socialAccount['reference'], + $socialAccount['token'], + ]; $this ->setTo($user['email']) ->setSubject($subject) - ->setViewVars(compact('user', 'socialAccount')); + ->setEmailFormat(Message::MESSAGE_BOTH) + ->setViewVars(compact('user', 'socialAccount', 'activationUrl')); $this ->viewBuilder() ->setTemplate('CakeDC/Users.socialAccountValidation'); From f4b8790270e7cb75335d016523921138678c207b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 15 Jan 2020 18:23:32 -0300 Subject: [PATCH 478/685] phpcs fixes --- src/Mailer/UsersMailer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index fb0e1aebc..8c7feac59 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -38,7 +38,7 @@ protected function validation(EntityInterface $user) $viewVars = [ 'activationUrl' => UsersUrl::actionUrl('validateEmail', [ '_full' => true, - $user->token + $user->token, ]), ] + $user->toArray(); @@ -69,7 +69,7 @@ protected function resetPassword(EntityInterface $user) $viewVars = [ 'activationUrl' => UsersUrl::actionUrl('resetPassword', [ '_full' => true, - $user->token + $user->token, ]), ] + $user->toArray(); From f927380104002729c0b397bd48d65d1ebd66e34c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 15 Jan 2020 18:23:52 -0300 Subject: [PATCH 479/685] phpcs fixes --- tests/TestCase/Mailer/UsersMailerTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index 0755d4bb4..8c05b4ea1 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -74,7 +74,7 @@ public function testValidation() 'controller' => 'Users', 'action' => 'validateEmail', '_full' => true, - '12345678' + '12345678', ], 'first_name' => 'FirstName', 'last_name' => 'Bond', @@ -117,7 +117,7 @@ public function testSocialAccountValidation() 'action' => 'validateAccount', 'Facebook', 'reference-1-1234', - 'token-1234' + 'token-1234', ], ]; @@ -149,7 +149,7 @@ public function testResetPassword() 'controller' => 'Users', 'action' => 'resetPassword', '_full' => true, - '12345' + '12345', ], 'first_name' => 'FirstName', 'email' => 'test@example.com', From 0d0c6905eabb0b275f79dc72fd952601920f7791 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 15 Jan 2020 18:46:45 -0300 Subject: [PATCH 480/685] fixed dependencies --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 206dac8bd..6c475720a 100644 --- a/composer.json +++ b/composer.json @@ -32,8 +32,7 @@ "cakephp/cakephp": "^4.0.0", "cakedc/auth": "^6.0.0", "cakephp/authorization": "^2.0.0", - "cakephp/authentication": "^2.0.0", - "cakephp/cakephp-codesniffer": "dev-master" + "cakephp/authentication": "^2.0.0" }, "require-dev": { "phpunit/phpunit": "^8.0", @@ -46,7 +45,8 @@ "robthree/twofactorauth": "^1.6", "yubico/u2flib-server": "^1.0", "php-coveralls/php-coveralls": "^2.1", - "league/oauth1-client": "^1.7" + "league/oauth1-client": "^1.7", + "cakephp/cakephp-codesniffer": "^4.0" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", From 303561cbc60bdd0847b2a7453b9721e54a9cf9c5 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 15 Jan 2020 18:50:26 -0300 Subject: [PATCH 481/685] phpstan fixes --- src/Mailer/UsersMailer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 8c7feac59..7891784cf 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -38,7 +38,7 @@ protected function validation(EntityInterface $user) $viewVars = [ 'activationUrl' => UsersUrl::actionUrl('validateEmail', [ '_full' => true, - $user->token, + $user['token'], ]), ] + $user->toArray(); @@ -69,7 +69,7 @@ protected function resetPassword(EntityInterface $user) $viewVars = [ 'activationUrl' => UsersUrl::actionUrl('resetPassword', [ '_full' => true, - $user->token, + $user['token'], ]), ] + $user->toArray(); From 8772a855243c686a48727df8183e6dd21380fcbb Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Jan 2020 15:21:47 -0300 Subject: [PATCH 482/685] phpcs fix --- src/Mailer/UsersMailer.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 7891784cf..931923c64 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -43,10 +43,10 @@ protected function validation(EntityInterface $user) ] + $user->toArray(); $this - ->setTo($user['email']) - ->setSubject($firstName . $subject) + ->setTo($user['email']) + ->setSubject($firstName . $subject) ->setEmailFormat(Message::MESSAGE_BOTH) - ->setViewVars($viewVars); + ->setViewVars($viewVars); $this->viewBuilder() ->setTemplate('CakeDC/Users.validation'); From 8caba36175f8f7ae1c195b4a353db276b985bbb0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Jan 2020 15:22:40 -0300 Subject: [PATCH 483/685] avoid undefined index warning --- src/Mailer/UsersMailer.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 931923c64..7e3ab2985 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -102,9 +102,9 @@ protected function socialAccountValidation(EntityInterface $user, EntityInterfac 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', 'action' => 'validateAccount', - $socialAccount['provider'], - $socialAccount['reference'], - $socialAccount['token'], + $socialAccount['provider'] ?? null, + $socialAccount['reference'] ?? null, + $socialAccount['token'] ?? null, ]; $this ->setTo($user['email']) From 151c2bf9cec68f1f6596179325471b3b25b36247 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Jan 2020 15:26:06 -0300 Subject: [PATCH 484/685] corrected misspelled word --- src/Utility/UsersUrl.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Utility/UsersUrl.php b/src/Utility/UsersUrl.php index fcce64c7b..52fbd36b0 100644 --- a/src/Utility/UsersUrl.php +++ b/src/Utility/UsersUrl.php @@ -48,7 +48,7 @@ public static function actionUrl($action, $extra = []) } /** - * Get an user action route. This should not be user for links like HtmlHelper::link + * Get an user action route. This should not be used for links like HtmlHelper::link * * @param string $action user action * @return array @@ -59,7 +59,7 @@ public static function actionRouteParams($action) } /** - * Get an user action route. This should not be user for links like HtmlHelper::link + * Get an user action route. This should not be used for links like HtmlHelper::link * * @param string $action user action * @return array From 2fffbbada3fbb875fa4a72bcae976941a85625c9 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sat, 25 Jan 2020 14:58:07 -0300 Subject: [PATCH 485/685] phpstan/phpstan is now a phar, this avoid issue with dependency conflicts --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6c475720a..c848d80fd 100644 --- a/composer.json +++ b/composer.json @@ -85,7 +85,7 @@ "test": "phpunit --stderr", "stan": "phpstan analyse src/", "psalm": "php vendor/psalm/phar/psalm.phar --show-info=false src/ ", - "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan-shim:^0.11.18 psalm/phar:^3.5 && mv composer.backup composer.json", + "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12 psalm/phar:^3.5 && mv composer.backup composer.json", "stan-rebuild-baseline": "phpstan analyse --configuration phpstan.neon --error-format baselineNeon src/ > phpstan-baseline.neon", "psalm-rebuild-baseline": "php vendor/psalm/phar/psalm.phar --show-info=false --set-baseline=psalm-baseline.xml src/", "rector": "rector process src/", From 1d0d8a6a0346cbfdd77a18297b46b230a22fd575 Mon Sep 17 00:00:00 2001 From: Maxime Date: Wed, 29 Jan 2020 15:02:28 +0100 Subject: [PATCH 486/685] Update tests, remove sessions, authed users and fixtures. Use only MOCK to test the postLinks --- .phpunit.result.cache | 1 + .../View/Helper/AuthLinkHelperTest.php | 29 ++++--------------- 2 files changed, 7 insertions(+), 23 deletions(-) create mode 100644 .phpunit.result.cache diff --git a/.phpunit.result.cache b/.phpunit.result.cache new file mode 100644 index 000000000..7d3ca36d4 --- /dev/null +++ b/.phpunit.result.cache @@ -0,0 +1 @@ +C:37:"PHPUnit\Runner\DefaultTestResultCache":51387:{a:2:{s:7:"defects";a:12:{s:92:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountHappy";i:6;s:99:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountInvalidToken";i:6;s:100:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountAlreadyActive";i:6;s:93:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationHappy";i:6;s:98:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationEmailError";i:6;s:95:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationInvalid";i:6;s:101:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationAlreadyActive";i:6;s:108:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testCallbackLinkSocialWithValidationErrors";i:6;s:99:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterValidatorOption";i:6;s:105:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testPostLinkAuthorizedAllowedTrueLoggedAsAdmin";i:6;s:110:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testPostLinkAuthorizedAllowedFalseLoggedWithoutRole";i:4;s:82:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testLinkAuthorizedHappy";i:4;}s:5:"times";a:492:{s:97:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateNoSocialService";d:0.498;s:107:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateSuccessfullyAuthenticated";d:1.275;s:96:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateGetRawDataNull";d:0.097;s:94:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateErrorNoEmail";d:0.016;s:104:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateIdentifierReturnedNull";d:0.003;s:113:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateErrorException with data set #0";d:0.055;s:113:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateErrorException with data set #1";d:0.001;s:104:"CakeDC\Users\Test\TestCase\Authenticator\SocialPendingEmailAuthenticatorTest::testAuthenticateInvalidUrl";d:0.086;s:104:"CakeDC\Users\Test\TestCase\Authenticator\SocialPendingEmailAuthenticatorTest::testAuthenticateBaseFailed";d:0.119;s:103:"CakeDC\Users\Test\TestCase\Controller\Component\SetupComponentTest::testInitialization with data set #0";d:0.163;s:103:"CakeDC\Users\Test\TestCase\Controller\Component\SetupComponentTest::testInitialization with data set #1";d:0.001;s:103:"CakeDC\Users\Test\TestCase\Controller\Component\SetupComponentTest::testInitialization with data set #2";d:0.001;s:103:"CakeDC\Users\Test\TestCase\Controller\Component\SetupComponentTest::testInitialization with data set #3";d:0.001;s:103:"CakeDC\Users\Test\TestCase\Controller\Component\SetupComponentTest::testInitialization with data set #4";d:0.001;s:92:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountHappy";d:0.138;s:99:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountInvalidToken";d:0.001;s:100:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountAlreadyActive";d:0;s:93:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationHappy";d:0.001;s:98:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationEmailError";d:0.001;s:95:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationInvalid";d:0.001;s:101:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationAlreadyActive";d:0.001;s:89:"CakeDC\Users\Test\TestCase\Controller\Traits\CustomUsersTableTraitTest::testGetUsersTable";d:0.02;s:85:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testLinkSocialHappy";d:0.249;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testCallbackLinkSocialHappy";d:0.121;s:108:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testCallbackLinkSocialWithValidationErrors";d:0.016;s:102:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testCallbackLinkSocialQueryHasErrors";d:0.101;s:103:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testCallbackLinkSocialUnknownProvider";d:0.135;s:75:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLoginHappy";d:0.056;s:76:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLoginRehash";d:0.18;s:73:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLoginGet";d:0.012;s:71:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogout";d:0.025;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogin with data set #0";d:0.011;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogin with data set #1";d:0.011;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogin with data set #2";d:0.012;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogin with data set #3";d:0.015;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogin with data set #4";d:0.012;s:83:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testSocialLoginSuccess";d:0.013;s:92:"CakeDC\Users\Test\TestCase\Controller\Traits\OneTimePasswordVerifyTraitTest::testVerifyHappy";d:0.023;s:97:"CakeDC\Users\Test\TestCase\Controller\Traits\OneTimePasswordVerifyTraitTest::testVerifyNotEnabled";d:0.028;s:96:"CakeDC\Users\Test\TestCase\Controller\Traits\OneTimePasswordVerifyTraitTest::testVerifyGetShowQR";d:0.048;s:108:"CakeDC\Users\Test\TestCase\Controller\Traits\OneTimePasswordVerifyTraitTest::testVerifyGetGeneratesNewSecret";d:0.056;s:114:"CakeDC\Users\Test\TestCase\Controller\Traits\OneTimePasswordVerifyTraitTest::testVerifyGetDoesNotGenerateNewSecret";d:0.051;s:97:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordHappy";d:0.257;s:101:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithError";d:0.098;s:112:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithAfterChangeEvent";d:0.329;s:108:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithSamePassword";d:0.343;s:116:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithEmptyCurrentPassword";d:0.341;s:116:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithWrongCurrentPassword";d:0.25;s:107:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithInvalidUser";d:0.224;s:103:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordGetLoggedIn";d:0.099;s:129:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordGetNotLoggedInInsideResetPasswordFlow";d:0.012;s:130:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordGetNotLoggedInOutsideResetPasswordFlow";d:0.011;s:91:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testResetPassword";d:0.013;s:101:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestResetPasswordGet";d:0.013;s:98:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestPasswordHappy";d:0.235;s:104:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestPasswordInvalidUser";d:0.089;s:107:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestPasswordEmptyReference";d:0.088;s:134:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testEnsureUserActiveForResetPasswordFeature with data set #0";d:0.013;s:134:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testEnsureUserActiveForResetPasswordFeature with data set #1";d:0.036;s:135:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestGoogleAuthTokenResetWithValidUser with data set #0";d:0.021;s:135:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestGoogleAuthTokenResetWithValidUser with data set #1";d:0.012;s:135:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestGoogleAuthTokenResetWithValidUser with data set #2";d:0.011;s:135:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestGoogleAuthTokenResetWithValidUser with data set #3";d:0.012;s:135:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestGoogleAuthTokenResetWithValidUser with data set #4";d:0.013;s:100:"CakeDC\Users\Test\TestCase\Controller\Traits\ProfileTraitTest::testProfileGetNotLoggedInUserNotFound";d:0.012;s:97:"CakeDC\Users\Test\TestCase\Controller\Traits\ProfileTraitTest::testProfileGetLoggedInUserNotFound";d:0.088;s:95:"CakeDC\Users\Test\TestCase\Controller\Traits\ProfileTraitTest::testProfileGetNotLoggedInEmptyId";d:0.019;s:94:"CakeDC\Users\Test\TestCase\Controller\Traits\ProfileTraitTest::testProfileGetLoggedInMyProfile";d:0.094;s:91:"CakeDC\Users\Test\TestCase\Controller\Traits\ReCaptchaTraitTest::testValidateValidReCaptcha";d:0.033;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\ReCaptchaTraitTest::testValidateInvalidReCaptcha";d:0.004;s:89:"CakeDC\Users\Test\TestCase\Controller\Traits\ReCaptchaTraitTest::testGetRecaptchaInstance";d:0.015;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\ReCaptchaTraitTest::testGetRecaptchaInstanceNull";d:0.001;s:91:"CakeDC\Users\Test\TestCase\Controller\Traits\ReCaptchaTraitTest::testValidateReCaptchaFalse";d:0.001;s:81:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testValidateEmail";d:0.011;s:76:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegister";d:0.107;s:96:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterWithEventFalseResult";d:0.013;s:98:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterWithEventSuccessResult";d:0.111;s:85:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterReCaptcha";d:0.101;s:92:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterValidationErrors";d:0.011;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterRecaptchaNotValid";d:0.014;s:79:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterGet";d:0.013;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterRecaptchaDisabled";d:0.156;s:86:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterNotEnabled";d:0.048;s:95:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterLoggedInUserAllowed";d:0.386;s:98:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterLoggedInUserNotAllowed";d:0.184;s:75:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testIndex";d:0.01;s:74:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testView";d:0.025;s:82:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testViewNotFound";d:0.015;s:83:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testViewInvalidPK";d:0.012;s:76:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testAddGet";d:0.012;s:82:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testAddPostHappy";d:0.112;s:83:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testAddPostErrors";d:0.013;s:83:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testEditPostHappy";d:0.016;s:84:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testEditPostErrors";d:0.015;s:81:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testDeleteHappy";d:0.023;s:84:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testDeleteNotFound";d:0.026;s:84:"CakeDC\Users\Test\TestCase\Controller\Traits\SocialTraitTest::testSocialEmailSuccess";d:0.009;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fCustomUser with data set #0";d:0.028;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fCustomUser with data set #1";d:0.02;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fCustomUser with data set #2";d:0.013;s:78:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fRegisterOkay";d:0.027;s:99:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fRegisterRedirect with data set #0";d:0.01;s:99:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fRegisterRedirect with data set #1";d:0.017;s:84:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fRegisterFinishOkay";d:0.036;s:89:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fRegisterFinishException";d:0.015;s:113:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fAuthenticateRedirectCustomUser with data set #0";d:0.014;s:113:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fAuthenticateRedirectCustomUser with data set #1";d:0.026;s:78:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fAuthenticate";d:0.024;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fAutheticateFinishOkay";d:0.069;s:96:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fAutheticateFinishWithException";d:0.029;s:92:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateHappyEmail";d:0.022;s:94:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateUserNotFound";d:0.016;s:94:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateTokenExpired";d:0.021;s:112:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateTokenExpiredWithOnExpiredEvent";d:0.015;s:91:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateInvalidOp";d:0.009;s:95:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateHappyPassword";d:0.012;s:100:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testResendTokenValidationHappy";d:0.03;s:130:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testResendTokenValidationWithAfterResendTokenValidationEvent";d:0.032;s:108:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testResendTokenValidationAlreadyActive";d:0.028;s:103:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testResendTokenValidationNotFound";d:0.01;s:85:"CakeDC\Users\Test\TestCase\Exception\AccountAlreadyActiveExceptionTest::testConstruct";d:0.007;s:81:"CakeDC\Users\Test\TestCase\Exception\AccountNotActiveExceptionTest::testConstruct";d:0;s:77:"CakeDC\Users\Test\TestCase\Exception\MissingEmailExceptionTest::testConstruct";d:0;s:77:"CakeDC\Users\Test\TestCase\Exception\TokenExpiredExceptionTest::testConstruct";d:0;s:82:"CakeDC\Users\Test\TestCase\Exception\UserAlreadyActiveExceptionTest::testConstruct";d:0;s:78:"CakeDC\Users\Test\TestCase\Exception\UserNotActiveExceptionTest::testConstruct";d:0;s:77:"CakeDC\Users\Test\TestCase\Exception\UserNotFoundExceptionTest::testConstruct";d:0.001;s:78:"CakeDC\Users\Test\TestCase\Exception\WrongPasswordExceptionTest::testConstruct";d:0;s:92:"CakeDC\Users\Test\TestCase\Identifier\SocialIdentifierTest::testIdentifyWithoutSocialAuthKey";d:0;s:72:"CakeDC\Users\Test\TestCase\Identifier\SocialIdentifierTest::testIdentify";d:0.087;s:88:"CakeDC\Users\Test\TestCase\Identifier\SocialIdentifierTest::testIdentifyErrorSocialLogin";d:0;s:79:"CakeDC\Users\Test\TestCase\Identifier\SocialIdentifierTest::testIdentifyNoEmail";d:0.003;s:64:"CakeDC\Users\Test\TestCase\Email\UsersMailerTest::testValidation";d:0.002;s:77:"CakeDC\Users\Test\TestCase\Email\UsersMailerTest::testSocialAccountValidation";d:0.002;s:67:"CakeDC\Users\Test\TestCase\Email\UsersMailerTest::testResetPassword";d:0.002;s:82:"CakeDC\Users\Test\TestCase\Middleware\SocialAuthMiddlewareTest::testProceedStepOne";d:0.026;s:93:"CakeDC\Users\Test\TestCase\Middleware\SocialAuthMiddlewareTest::testSuccessfullyAuthenticated";d:0.001;s:114:"CakeDC\Users\Test\TestCase\Middleware\SocialAuthMiddlewareTest::testSocialAuthenticationException with data set #0";d:0.001;s:114:"CakeDC\Users\Test\TestCase\Middleware\SocialAuthMiddlewareTest::testSocialAuthenticationException with data set #1";d:0.002;s:82:"CakeDC\Users\Test\TestCase\Middleware\SocialAuthMiddlewareTest::testNotValidAction";d:0.001;s:82:"CakeDC\Users\Test\TestCase\Middleware\SocialEmailMiddlewareTest::testWithGetRquest";d:0.017;s:80:"CakeDC\Users\Test\TestCase\Middleware\SocialEmailMiddlewareTest::testWithoutUser";d:0.001;s:77:"CakeDC\Users\Test\TestCase\Middleware\SocialEmailMiddlewareTest::testWithUser";d:0.001;s:81:"CakeDC\Users\Test\TestCase\Middleware\SocialEmailMiddlewareTest::testWithoutEmail";d:0.001;s:83:"CakeDC\Users\Test\TestCase\Middleware\SocialEmailMiddlewareTest::testNotValidAction";d:0.001;s:80:"CakeDC\Users\Test\TestCase\Model\Behavior\AuthFinderBehaviorTest::testFindActive";d:0.013;s:100:"CakeDC\Users\Test\TestCase\Model\Behavior\AuthFinderBehaviorTest::testFindAuthBadMethodCallException";d:0.01;s:78:"CakeDC\Users\Test\TestCase\Model\Behavior\AuthFinderBehaviorTest::testFindAuth";d:0.001;s:128:"CakeDC\Users\Test\TestCase\Model\Behavior\LinkSocialBehaviorTest::testlinkSocialAccountFacebookProvider with data set "provider"";d:0.018;s:139:"CakeDC\Users\Test\TestCase\Model\Behavior\LinkSocialBehaviorTest::testlinkSocialAccountErrorSavingFacebookProvider with data set "provider"";d:0.03;s:141:"CakeDC\Users\Test\TestCase\Model\Behavior\LinkSocialBehaviorTest::testlinkSocialAccountFacebookProviderAccountExists with data set "provider"";d:0.024;s:78:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetToken";d:0.004;s:87:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenSendEmail";d:0.003;s:92:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenWithNullParams";d:0.003;s:90:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenNoExpiration";d:0.001;s:93:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenNotExistingUser";d:0.003;s:95:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenUserAlreadyActive";d:0.006;s:91:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenUserNotActive";d:0.003;s:88:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenUserActive";d:0.01;s:82:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testChangePassword";d:0.201;s:81:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testEmailOverride";d:0.007;s:99:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterNoValidateEmail";d:0.097;s:93:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterEmptyUser";d:0.001;s:103:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterValidateEmailAndTos";d:0.115;s:99:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterValidatorOption";d:0.001;s:95:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterTosRequired";d:0.094;s:97:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterNoTosRequired";d:0.132;s:80:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testActivateUser";d:0.002;s:76:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidate";d:0.006;s:96:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateUserWithExpiredToken";d:0.002;s:91:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateNotExistingUser";d:0.002;s:99:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testActiveUserRemoveValidationToken";d:0.002;s:92:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testRegisterUsingDefaultRole";d:0.1;s:91:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testRegisterUsingCustomRole";d:0.104;s:86:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testValidateEmail";d:0.006;s:98:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testValidateEmailInvalidToken";d:0.002;s:97:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testValidateEmailInvalidUser";d:0.001;s:99:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testValidateEmailActiveAccount";d:0.001;s:110:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testAfterSaveSocialNotActiveUserNotActive";d:0.005;s:104:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testAfterSaveSocialActiveUserActive";d:0.001;s:107:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testAfterSaveSocialActiveUserNotActive";d:0.003;s:118:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginFacebookProvider with data set "provider"";d:0.408;s:128:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginFacebookProviderUsingEmail with data set "provider"";d:0.296;s:123:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginExistingReferenceOkay with data set "provider"";d:0.004;s:128:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginExistingNotActiveReference with data set "provider"";d:0.003;s:132:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginExistingReferenceNotActiveUser with data set "provider"";d:0.005;s:109:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginNoEmail with data set "provider"";d:0.002;s:105:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testGenerateUniqueUsername with data set #0";d:0.004;s:105:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testGenerateUniqueUsername with data set #1";d:0.002;s:105:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testGenerateUniqueUsername with data set #2";d:0.002;s:71:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testTokenExpiredEmpty";d:0;s:72:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testTokenExpiredNotYet";d:0;s:66:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testTokenExpired";d:0;s:72:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testTokenExpiredLocale";d:0;s:75:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testPasswordsAreEncrypted";d:0.153;s:82:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testConfirmPasswordsAreEncrypted";d:0.165;s:67:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testCheckPassword";d:0.172;s:63:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testGetAvatar";d:0;s:65:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testUpdateToken";d:0;s:73:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testUpdateTokenExisting";d:0;s:68:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testUpdateTokenAdd";d:0.02;s:76:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testUpdateTokenExistingAdd";d:0.001;s:83:"CakeDC\Users\Test\TestCase\Model\Table\SocialAccountsTableTest::testValidationHappy";d:0.001;s:90:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testValidateRegisterNoValidateEmail";d:0.087;s:84:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testValidateRegisterEmptyUser";d:0.003;s:88:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testValidateRegisterValidateEmail";d:0.156;s:86:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testValidateRegisterTosRequired";d:0.098;s:88:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testValidateRegisterNoTosRequired";d:0.199;s:71:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testActivateUser";d:0.003;s:70:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testSocialLogin";d:0.04;s:85:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testSocialLoginInactiveAccount";d:0.003;s:103:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testSocialLoginCreateNewAccountWithNoCredentials";d:0.138;s:86:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testSocialLoginCreateNewAccount";d:0.175;s:53:"CakeDC\Users\Test\TestCase\PluginTest::testMiddleware";d:0.062;s:93:"CakeDC\Users\Test\TestCase\PluginTest::testMiddlewareAuthorizationMiddlewareAndRbacMiddleware";d:0;s:72:"CakeDC\Users\Test\TestCase\PluginTest::testMiddlewareWithoutAuhorization";d:0;s:62:"CakeDC\Users\Test\TestCase\PluginTest::testMiddlewareNotSocial";d:0;s:84:"CakeDC\Users\Test\TestCase\PluginTest::testMiddlewareNotOneTimePasswordAuthenticator";d:0;s:88:"CakeDC\Users\Test\TestCase\PluginTest::testMiddlewareNotGoogleAuthenticationAndNotSocial";d:0;s:82:"CakeDC\Users\Test\TestCase\PluginTest::testGetAuthenticationServiceCallableDefined";d:0.001;s:67:"CakeDC\Users\Test\TestCase\PluginTest::testGetAuthenticationService";d:0.048;s:101:"CakeDC\Users\Test\TestCase\PluginTest::testGetAuthenticationServiceWithouOneTimePasswordAuthenticator";d:0.001;s:66:"CakeDC\Users\Test\TestCase\PluginTest::testGetAuthorizationService";d:0.19;s:81:"CakeDC\Users\Test\TestCase\PluginTest::testGetAuthorizationServiceCallableDefined";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #0";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #1";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #2";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #3";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #4";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #5";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #6";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #7";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #8";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #9";d:0;s:70:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #10";d:0;s:60:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddUser";d:0.21;s:72:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddUserWithNoParams";d:0.108;s:65:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddSuperuser";d:0.228;s:77:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddSuperuserWithNoParams";d:0.155;s:70:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testResetAllPasswords";d:0.003;s:85:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testResetAllPasswordsNoPassingParams";d:0.02;s:66:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testResetPassword";d:0.094;s:63:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testChangeRole";d:0.006;s:65:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testActivateUser";d:0.003;s:63:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testDeleteUser";d:0.016;s:70:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddUserCustomRole";d:0.117;s:71:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddUserDefaultRole";d:0.12;s:77:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddUserCustomDefaultRole";d:0.116;s:73:"CakeDC\Users\Test\TestCase\Traits\RandomStringTraitTest::testRandomString";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #0";d:0.002;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #1";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #2";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #3";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #4";d:0.002;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #5";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #6";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #7";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #8";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #9";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #10";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #11";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #12";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #13";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #14";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #15";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #16";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #17";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #18";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #19";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #20";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #21";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #22";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #23";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #24";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #25";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #26";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #27";d:0.001;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #28";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #29";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #30";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #31";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #32";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #33";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #34";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #35";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #36";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #37";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #38";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #39";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #40";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #41";d:0.001;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #42";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #43";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #44";d:0.001;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #45";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #46";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #47";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #48";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #49";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #50";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #51";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #52";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #53";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #54";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #55";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #56";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #57";d:0.001;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #58";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #59";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #60";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #61";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #62";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #63";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #64";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #65";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #66";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #67";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #68";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #69";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #70";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #71";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #0";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #1";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #2";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #3";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #4";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #5";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #6";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #7";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #8";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #9";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #10";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #11";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #12";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #13";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #14";d:0.001;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #15";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #16";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #17";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #18";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #19";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #20";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #21";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #22";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #23";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #24";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #25";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #26";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #27";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #28";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #29";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #30";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #31";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #32";d:0.001;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #33";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #34";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #35";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #36";d:0.001;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #37";d:0.001;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #38";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #39";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #40";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #41";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #42";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #43";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #44";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #45";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #46";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #47";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #48";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #49";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #50";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #51";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #52";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #53";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #54";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #55";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #56";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #57";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #58";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #59";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #60";d:0.001;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #61";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #62";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #63";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #64";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #65";d:0.002;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #66";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #67";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #68";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #69";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #70";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #71";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #0";d:0.001;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #1";d:0.001;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #2";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #3";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #4";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #5";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #6";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #7";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #8";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #9";d:0.001;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #10";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #11";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #12";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #13";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #14";d:0.003;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #15";d:0.001;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #16";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #17";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #18";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #19";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #20";d:0.001;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #21";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #22";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #23";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #24";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #25";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #26";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #27";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #28";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #29";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #30";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #31";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #32";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #33";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #34";d:0.001;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #35";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #36";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #37";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #38";d:0.001;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #39";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #40";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #41";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #42";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #43";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #44";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #45";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #46";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #47";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #48";d:0.001;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #49";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #50";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #51";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #52";d:0.002;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #53";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #54";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #55";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #56";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #57";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #58";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #59";d:0.003;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #60";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #61";d:0.002;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #62";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #63";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #64";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #65";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #66";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #67";d:0.001;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #68";d:0.003;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #69";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #70";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #71";d:0;s:90:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testCheckActionOnRequest with data set #0";d:0;s:90:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testCheckActionOnRequest with data set #1";d:0.001;s:90:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testCheckActionOnRequest with data set #2";d:0;s:90:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testCheckActionOnRequest with data set #3";d:0;s:90:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testCheckActionOnRequest with data set #4";d:0;s:80:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testLinkFalseWithMock";d:0.028;s:82:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testLinkAuthorizedHappy";d:0.001;s:88:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testLinkAuthorizedAllowedTrue";d:0.001;s:89:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testLinkAuthorizedAllowedFalse";d:0.001;s:73:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testGetRequest";d:0.001;s:105:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testPostLinkAuthorizedAllowedTrueLoggedAsAdmin";d:0;s:110:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testPostLinkAuthorizedAllowedFalseLoggedWithoutRole";d:0;s:93:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testPostLinkAuthorizedAllowedFalse";d:0.001;s:65:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testLogout";d:0.019;s:81:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testLogoutDifferentMessage";d:0.001;s:76:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testLogoutWithOptions";d:0.001;s:66:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testWelcome";d:0.005;s:81:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testWelcomeNotLoggedInUser";d:0.001;s:71:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testAddReCaptcha";d:0.058;s:76:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testAddReCaptchaEmpty";d:0.001;s:77:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testAddReCaptchaScript";d:0.007;s:74:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialLoginLink";d:0.001;s:81:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialLoginTranslation";d:0.081;s:80:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialConnectLinkList";d:0.001;s:103:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialConnectLinkListIsConnectedWithFacebook";d:0.001;s:98:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialConnectLinkListSocialIsNotEnabled";d:0.001;s:117:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialConnectLinkListSocialEnabledButNotConfiguredProvider";d:0.001;}}} \ No newline at end of file diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php index 30121bb37..e134028a5 100644 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -15,8 +15,6 @@ use Cake\Http\ServerRequest; use Cake\Routing\Router; -use Cake\ORM\TableRegistry; -use Cake\TestSuite\IntegrationTestTrait; use Cake\TestSuite\TestCase; use Cake\View\View; use CakeDC\Users\View\Helper\AuthLinkHelper; @@ -148,26 +146,17 @@ public function testGetRequest() */ public function testPostLinkAuthorizedAllowedTrueLoggedAsAdmin() { - $this->userTable = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $this->session( - [ - 'Auth' => [ - 'User' => $this->userTable->get('00000000-0000-0000-0000-000000000001'), - ], - ] - ); $url = [ + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'delete', '00000000-0000-0000-0000-000000000010', ]; - $this->AuthLink->expects($this->once()) - ->method('isAuthorized') - ->with( - $this->equalTo($url) - ) + $this->AuthLink->expects($this->any()) + ->method('allowMethod') + ->with(['post', 'delete']) ->will($this->returnValue(true)); $link = $this->AuthLink->postLink('Post Link Title', $url, [ @@ -188,15 +177,8 @@ public function testPostLinkAuthorizedAllowedTrueLoggedAsAdmin() */ public function testPostLinkAuthorizedAllowedFalseLoggedWithoutRole() { - $this->userTable = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); - $this->session( - [ - 'Auth' => [ - 'User' => $this->userTable->get('00000000-0000-0000-0000-000000000004'), - ], - ] - ); $url = [ + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'delete', @@ -227,6 +209,7 @@ public function testPostLinkAuthorizedAllowedFalseLoggedWithoutRole() public function testPostLinkAuthorizedAllowedFalse() { $url = [ + 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'delete', From 37651683a9f91acdb4dd63371cc6fc2c4a608de1 Mon Sep 17 00:00:00 2001 From: Maxime Date: Wed, 29 Jan 2020 15:32:40 +0100 Subject: [PATCH 487/685] remove phpunit result cache file --- .phpunit.result.cache | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .phpunit.result.cache diff --git a/.phpunit.result.cache b/.phpunit.result.cache deleted file mode 100644 index da1157e1b..000000000 --- a/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -C:37:"PHPUnit\Runner\DefaultTestResultCache":51313:{a:2:{s:7:"defects";a:12:{s:92:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountHappy";i:6;s:99:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountInvalidToken";i:6;s:100:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountAlreadyActive";i:6;s:93:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationHappy";i:6;s:98:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationEmailError";i:6;s:95:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationInvalid";i:6;s:101:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationAlreadyActive";i:6;s:108:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testCallbackLinkSocialWithValidationErrors";i:6;s:99:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterValidatorOption";i:6;s:105:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testPostLinkAuthorizedAllowedTrueLoggedAsAdmin";i:6;s:110:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testPostLinkAuthorizedAllowedFalseLoggedWithoutRole";i:4;s:82:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testLinkAuthorizedHappy";i:4;}s:5:"times";a:492:{s:97:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateNoSocialService";d:0.428;s:107:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateSuccessfullyAuthenticated";d:0.773;s:96:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateGetRawDataNull";d:0.032;s:94:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateErrorNoEmail";d:0.014;s:104:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateIdentifierReturnedNull";d:0.001;s:113:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateErrorException with data set #0";d:0.025;s:113:"CakeDC\Users\Test\TestCase\Authenticator\SocialAuthenticatorTest::testAuthenticateErrorException with data set #1";d:0.001;s:104:"CakeDC\Users\Test\TestCase\Authenticator\SocialPendingEmailAuthenticatorTest::testAuthenticateInvalidUrl";d:0.064;s:104:"CakeDC\Users\Test\TestCase\Authenticator\SocialPendingEmailAuthenticatorTest::testAuthenticateBaseFailed";d:0.095;s:103:"CakeDC\Users\Test\TestCase\Controller\Component\SetupComponentTest::testInitialization with data set #0";d:0.061;s:103:"CakeDC\Users\Test\TestCase\Controller\Component\SetupComponentTest::testInitialization with data set #1";d:0.001;s:103:"CakeDC\Users\Test\TestCase\Controller\Component\SetupComponentTest::testInitialization with data set #2";d:0.001;s:103:"CakeDC\Users\Test\TestCase\Controller\Component\SetupComponentTest::testInitialization with data set #3";d:0;s:103:"CakeDC\Users\Test\TestCase\Controller\Component\SetupComponentTest::testInitialization with data set #4";d:0;s:92:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountHappy";d:0.091;s:99:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountInvalidToken";d:0.001;s:100:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testValidateAccountAlreadyActive";d:0.002;s:93:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationHappy";d:0.001;s:98:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationEmailError";d:0.001;s:95:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationInvalid";d:0.001;s:101:"CakeDC\Users\Test\TestCase\Controller\SocialAccountsControllerTest::testResendValidationAlreadyActive";d:0.001;s:89:"CakeDC\Users\Test\TestCase\Controller\Traits\CustomUsersTableTraitTest::testGetUsersTable";d:0.018;s:85:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testLinkSocialHappy";d:0.227;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testCallbackLinkSocialHappy";d:0.103;s:108:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testCallbackLinkSocialWithValidationErrors";d:0.01;s:102:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testCallbackLinkSocialQueryHasErrors";d:0.099;s:103:"CakeDC\Users\Test\TestCase\Controller\Traits\LinkSocialTraitTest::testCallbackLinkSocialUnknownProvider";d:0.106;s:75:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLoginHappy";d:0.045;s:76:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLoginRehash";d:0.2;s:73:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLoginGet";d:0.012;s:71:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogout";d:0.027;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogin with data set #0";d:0.011;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogin with data set #1";d:0.011;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogin with data set #2";d:0.013;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogin with data set #3";d:0.018;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testLogin with data set #4";d:0.012;s:83:"CakeDC\Users\Test\TestCase\Controller\Traits\LoginTraitTest::testSocialLoginSuccess";d:0.013;s:92:"CakeDC\Users\Test\TestCase\Controller\Traits\OneTimePasswordVerifyTraitTest::testVerifyHappy";d:0.015;s:97:"CakeDC\Users\Test\TestCase\Controller\Traits\OneTimePasswordVerifyTraitTest::testVerifyNotEnabled";d:0.012;s:96:"CakeDC\Users\Test\TestCase\Controller\Traits\OneTimePasswordVerifyTraitTest::testVerifyGetShowQR";d:0.021;s:108:"CakeDC\Users\Test\TestCase\Controller\Traits\OneTimePasswordVerifyTraitTest::testVerifyGetGeneratesNewSecret";d:0.014;s:114:"CakeDC\Users\Test\TestCase\Controller\Traits\OneTimePasswordVerifyTraitTest::testVerifyGetDoesNotGenerateNewSecret";d:0.011;s:97:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordHappy";d:0.289;s:101:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithError";d:0.102;s:112:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithAfterChangeEvent";d:0.248;s:108:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithSamePassword";d:0.255;s:116:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithEmptyCurrentPassword";d:0.159;s:116:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithWrongCurrentPassword";d:0.252;s:107:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordWithInvalidUser";d:0.178;s:103:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordGetLoggedIn";d:0.094;s:129:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordGetNotLoggedInInsideResetPasswordFlow";d:0.015;s:130:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testChangePasswordGetNotLoggedInOutsideResetPasswordFlow";d:0.013;s:91:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testResetPassword";d:0.02;s:101:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestResetPasswordGet";d:0.011;s:98:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestPasswordHappy";d:0.242;s:104:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestPasswordInvalidUser";d:0.087;s:107:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestPasswordEmptyReference";d:0.086;s:134:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testEnsureUserActiveForResetPasswordFeature with data set #0";d:0.012;s:134:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testEnsureUserActiveForResetPasswordFeature with data set #1";d:0.042;s:135:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestGoogleAuthTokenResetWithValidUser with data set #0";d:0.019;s:135:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestGoogleAuthTokenResetWithValidUser with data set #1";d:0.014;s:135:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestGoogleAuthTokenResetWithValidUser with data set #2";d:0.014;s:135:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestGoogleAuthTokenResetWithValidUser with data set #3";d:0.014;s:135:"CakeDC\Users\Test\TestCase\Controller\Traits\PasswordManagementTraitTest::testRequestGoogleAuthTokenResetWithValidUser with data set #4";d:0.012;s:100:"CakeDC\Users\Test\TestCase\Controller\Traits\ProfileTraitTest::testProfileGetNotLoggedInUserNotFound";d:0.012;s:97:"CakeDC\Users\Test\TestCase\Controller\Traits\ProfileTraitTest::testProfileGetLoggedInUserNotFound";d:0.097;s:95:"CakeDC\Users\Test\TestCase\Controller\Traits\ProfileTraitTest::testProfileGetNotLoggedInEmptyId";d:0.017;s:94:"CakeDC\Users\Test\TestCase\Controller\Traits\ProfileTraitTest::testProfileGetLoggedInMyProfile";d:0.092;s:91:"CakeDC\Users\Test\TestCase\Controller\Traits\ReCaptchaTraitTest::testValidateValidReCaptcha";d:0.021;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\ReCaptchaTraitTest::testValidateInvalidReCaptcha";d:0.004;s:89:"CakeDC\Users\Test\TestCase\Controller\Traits\ReCaptchaTraitTest::testGetRecaptchaInstance";d:0.016;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\ReCaptchaTraitTest::testGetRecaptchaInstanceNull";d:0.001;s:91:"CakeDC\Users\Test\TestCase\Controller\Traits\ReCaptchaTraitTest::testValidateReCaptchaFalse";d:0.001;s:81:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testValidateEmail";d:0.013;s:76:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegister";d:0.119;s:96:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterWithEventFalseResult";d:0.01;s:98:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterWithEventSuccessResult";d:0.118;s:85:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterReCaptcha";d:0.103;s:92:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterValidationErrors";d:0.012;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterRecaptchaNotValid";d:0.01;s:79:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterGet";d:0.011;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterRecaptchaDisabled";d:0.104;s:86:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterNotEnabled";d:0.026;s:95:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterLoggedInUserAllowed";d:0.195;s:98:"CakeDC\Users\Test\TestCase\Controller\Traits\RegisterTraitTest::testRegisterLoggedInUserNotAllowed";d:0.092;s:75:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testIndex";d:0.016;s:74:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testView";d:0.013;s:82:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testViewNotFound";d:0.013;s:83:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testViewInvalidPK";d:0.016;s:76:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testAddGet";d:0.013;s:82:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testAddPostHappy";d:0.091;s:83:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testAddPostErrors";d:0.013;s:83:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testEditPostHappy";d:0.019;s:84:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testEditPostErrors";d:0.016;s:81:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testDeleteHappy";d:0.034;s:84:"CakeDC\Users\Test\TestCase\Controller\Traits\SimpleCrudTraitTest::testDeleteNotFound";d:0.028;s:84:"CakeDC\Users\Test\TestCase\Controller\Traits\SocialTraitTest::testSocialEmailSuccess";d:0.011;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fCustomUser with data set #0";d:0.024;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fCustomUser with data set #1";d:0.011;s:93:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fCustomUser with data set #2";d:0.015;s:78:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fRegisterOkay";d:0.032;s:99:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fRegisterRedirect with data set #0";d:0.012;s:99:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fRegisterRedirect with data set #1";d:0.014;s:84:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fRegisterFinishOkay";d:0.018;s:89:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fRegisterFinishException";d:0.015;s:113:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fAuthenticateRedirectCustomUser with data set #0";d:0.014;s:113:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fAuthenticateRedirectCustomUser with data set #1";d:0.013;s:78:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fAuthenticate";d:0.014;s:87:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fAutheticateFinishOkay";d:0.024;s:96:"CakeDC\Users\Test\TestCase\Controller\Traits\U2fTraitTest::testU2fAutheticateFinishWithException";d:0.014;s:92:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateHappyEmail";d:0.015;s:94:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateUserNotFound";d:0.017;s:94:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateTokenExpired";d:0.016;s:112:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateTokenExpiredWithOnExpiredEvent";d:0.01;s:91:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateInvalidOp";d:0.012;s:95:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testValidateHappyPassword";d:0.014;s:100:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testResendTokenValidationHappy";d:0.03;s:130:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testResendTokenValidationWithAfterResendTokenValidationEvent";d:0.039;s:108:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testResendTokenValidationAlreadyActive";d:0.017;s:103:"CakeDC\Users\Test\TestCase\Controller\Traits\UserValidationTraitTest::testResendTokenValidationNotFound";d:0.013;s:85:"CakeDC\Users\Test\TestCase\Exception\AccountAlreadyActiveExceptionTest::testConstruct";d:0.004;s:81:"CakeDC\Users\Test\TestCase\Exception\AccountNotActiveExceptionTest::testConstruct";d:0;s:77:"CakeDC\Users\Test\TestCase\Exception\MissingEmailExceptionTest::testConstruct";d:0;s:77:"CakeDC\Users\Test\TestCase\Exception\TokenExpiredExceptionTest::testConstruct";d:0;s:82:"CakeDC\Users\Test\TestCase\Exception\UserAlreadyActiveExceptionTest::testConstruct";d:0;s:78:"CakeDC\Users\Test\TestCase\Exception\UserNotActiveExceptionTest::testConstruct";d:0;s:77:"CakeDC\Users\Test\TestCase\Exception\UserNotFoundExceptionTest::testConstruct";d:0;s:78:"CakeDC\Users\Test\TestCase\Exception\WrongPasswordExceptionTest::testConstruct";d:0;s:92:"CakeDC\Users\Test\TestCase\Identifier\SocialIdentifierTest::testIdentifyWithoutSocialAuthKey";d:0.001;s:72:"CakeDC\Users\Test\TestCase\Identifier\SocialIdentifierTest::testIdentify";d:0.084;s:88:"CakeDC\Users\Test\TestCase\Identifier\SocialIdentifierTest::testIdentifyErrorSocialLogin";d:0;s:79:"CakeDC\Users\Test\TestCase\Identifier\SocialIdentifierTest::testIdentifyNoEmail";d:0.003;s:64:"CakeDC\Users\Test\TestCase\Email\UsersMailerTest::testValidation";d:0.002;s:77:"CakeDC\Users\Test\TestCase\Email\UsersMailerTest::testSocialAccountValidation";d:0.006;s:67:"CakeDC\Users\Test\TestCase\Email\UsersMailerTest::testResetPassword";d:0.001;s:82:"CakeDC\Users\Test\TestCase\Middleware\SocialAuthMiddlewareTest::testProceedStepOne";d:0.021;s:93:"CakeDC\Users\Test\TestCase\Middleware\SocialAuthMiddlewareTest::testSuccessfullyAuthenticated";d:0.001;s:114:"CakeDC\Users\Test\TestCase\Middleware\SocialAuthMiddlewareTest::testSocialAuthenticationException with data set #0";d:0.002;s:114:"CakeDC\Users\Test\TestCase\Middleware\SocialAuthMiddlewareTest::testSocialAuthenticationException with data set #1";d:0.001;s:82:"CakeDC\Users\Test\TestCase\Middleware\SocialAuthMiddlewareTest::testNotValidAction";d:0;s:82:"CakeDC\Users\Test\TestCase\Middleware\SocialEmailMiddlewareTest::testWithGetRquest";d:0.015;s:80:"CakeDC\Users\Test\TestCase\Middleware\SocialEmailMiddlewareTest::testWithoutUser";d:0;s:77:"CakeDC\Users\Test\TestCase\Middleware\SocialEmailMiddlewareTest::testWithUser";d:0.001;s:81:"CakeDC\Users\Test\TestCase\Middleware\SocialEmailMiddlewareTest::testWithoutEmail";d:0.001;s:83:"CakeDC\Users\Test\TestCase\Middleware\SocialEmailMiddlewareTest::testNotValidAction";d:0.001;s:80:"CakeDC\Users\Test\TestCase\Model\Behavior\AuthFinderBehaviorTest::testFindActive";d:0.009;s:100:"CakeDC\Users\Test\TestCase\Model\Behavior\AuthFinderBehaviorTest::testFindAuthBadMethodCallException";d:0.006;s:78:"CakeDC\Users\Test\TestCase\Model\Behavior\AuthFinderBehaviorTest::testFindAuth";d:0.003;s:128:"CakeDC\Users\Test\TestCase\Model\Behavior\LinkSocialBehaviorTest::testlinkSocialAccountFacebookProvider with data set "provider"";d:0.025;s:139:"CakeDC\Users\Test\TestCase\Model\Behavior\LinkSocialBehaviorTest::testlinkSocialAccountErrorSavingFacebookProvider with data set "provider"";d:0.017;s:141:"CakeDC\Users\Test\TestCase\Model\Behavior\LinkSocialBehaviorTest::testlinkSocialAccountFacebookProviderAccountExists with data set "provider"";d:0.016;s:78:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetToken";d:0.006;s:87:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenSendEmail";d:0.003;s:92:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenWithNullParams";d:0.001;s:90:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenNoExpiration";d:0.001;s:93:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenNotExistingUser";d:0.002;s:95:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenUserAlreadyActive";d:0.004;s:91:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenUserNotActive";d:0.003;s:88:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testResetTokenUserActive";d:0.002;s:82:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testChangePassword";d:0.171;s:81:"CakeDC\Users\Test\TestCase\Model\Behavior\PasswordBehaviorTest::testEmailOverride";d:0.01;s:99:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterNoValidateEmail";d:0.081;s:93:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterEmptyUser";d:0.001;s:103:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterValidateEmailAndTos";d:0.095;s:99:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterValidatorOption";d:0;s:95:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterTosRequired";d:0.081;s:97:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateRegisterNoTosRequired";d:0.104;s:80:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testActivateUser";d:0.003;s:76:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidate";d:0.002;s:96:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateUserWithExpiredToken";d:0.002;s:91:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testValidateNotExistingUser";d:0.002;s:99:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testActiveUserRemoveValidationToken";d:0.004;s:92:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testRegisterUsingDefaultRole";d:0.084;s:91:"CakeDC\Users\Test\TestCase\Model\Behavior\RegisterBehaviorTest::testRegisterUsingCustomRole";d:0.084;s:86:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testValidateEmail";d:0.001;s:98:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testValidateEmailInvalidToken";d:0.001;s:97:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testValidateEmailInvalidUser";d:0.001;s:99:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testValidateEmailActiveAccount";d:0.001;s:110:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testAfterSaveSocialNotActiveUserNotActive";d:0.001;s:104:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testAfterSaveSocialActiveUserActive";d:0.001;s:107:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialAccountBehaviorTest::testAfterSaveSocialActiveUserNotActive";d:0.002;s:118:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginFacebookProvider with data set "provider"";d:0.238;s:128:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginFacebookProviderUsingEmail with data set "provider"";d:0.228;s:123:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginExistingReferenceOkay with data set "provider"";d:0.003;s:128:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginExistingNotActiveReference with data set "provider"";d:0.002;s:132:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginExistingReferenceNotActiveUser with data set "provider"";d:0.004;s:109:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testSocialLoginNoEmail with data set "provider"";d:0.004;s:105:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testGenerateUniqueUsername with data set #0";d:0.001;s:105:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testGenerateUniqueUsername with data set #1";d:0.001;s:105:"CakeDC\Users\Test\TestCase\Model\Behavior\SocialBehaviorTest::testGenerateUniqueUsername with data set #2";d:0.001;s:71:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testTokenExpiredEmpty";d:0;s:72:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testTokenExpiredNotYet";d:0.001;s:66:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testTokenExpired";d:0.001;s:72:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testTokenExpiredLocale";d:0;s:75:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testPasswordsAreEncrypted";d:0.163;s:82:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testConfirmPasswordsAreEncrypted";d:0.152;s:67:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testCheckPassword";d:0.165;s:63:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testGetAvatar";d:0;s:65:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testUpdateToken";d:0;s:73:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testUpdateTokenExisting";d:0;s:68:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testUpdateTokenAdd";d:0.02;s:76:"CakeDC\Users\Test\TestCase\Model\Entity\UserTest::testUpdateTokenExistingAdd";d:0;s:83:"CakeDC\Users\Test\TestCase\Model\Table\SocialAccountsTableTest::testValidationHappy";d:0.001;s:90:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testValidateRegisterNoValidateEmail";d:0.082;s:84:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testValidateRegisterEmptyUser";d:0.001;s:88:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testValidateRegisterValidateEmail";d:0.104;s:86:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testValidateRegisterTosRequired";d:0.08;s:88:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testValidateRegisterNoTosRequired";d:0.096;s:71:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testActivateUser";d:0.003;s:70:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testSocialLogin";d:0.018;s:85:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testSocialLoginInactiveAccount";d:0.002;s:103:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testSocialLoginCreateNewAccountWithNoCredentials";d:0.081;s:86:"CakeDC\Users\Test\TestCase\Model\Table\UsersTableTest::testSocialLoginCreateNewAccount";d:0.082;s:53:"CakeDC\Users\Test\TestCase\PluginTest::testMiddleware";d:0.042;s:93:"CakeDC\Users\Test\TestCase\PluginTest::testMiddlewareAuthorizationMiddlewareAndRbacMiddleware";d:0;s:72:"CakeDC\Users\Test\TestCase\PluginTest::testMiddlewareWithoutAuhorization";d:0;s:62:"CakeDC\Users\Test\TestCase\PluginTest::testMiddlewareNotSocial";d:0;s:84:"CakeDC\Users\Test\TestCase\PluginTest::testMiddlewareNotOneTimePasswordAuthenticator";d:0;s:88:"CakeDC\Users\Test\TestCase\PluginTest::testMiddlewareNotGoogleAuthenticationAndNotSocial";d:0;s:82:"CakeDC\Users\Test\TestCase\PluginTest::testGetAuthenticationServiceCallableDefined";d:0.001;s:67:"CakeDC\Users\Test\TestCase\PluginTest::testGetAuthenticationService";d:0.033;s:101:"CakeDC\Users\Test\TestCase\PluginTest::testGetAuthenticationServiceWithouOneTimePasswordAuthenticator";d:0.001;s:66:"CakeDC\Users\Test\TestCase\PluginTest::testGetAuthorizationService";d:0.065;s:81:"CakeDC\Users\Test\TestCase\PluginTest::testGetAuthorizationServiceCallableDefined";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #0";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #1";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #2";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #3";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #4";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #5";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #6";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #7";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #8";d:0;s:69:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #9";d:0;s:70:"CakeDC\Users\Test\TestCase\PluginTest::testBootstrap with data set #10";d:0;s:60:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddUser";d:0.183;s:72:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddUserWithNoParams";d:0.08;s:65:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddSuperuser";d:0.079;s:77:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddSuperuserWithNoParams";d:0.086;s:70:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testResetAllPasswords";d:0.001;s:85:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testResetAllPasswordsNoPassingParams";d:0.016;s:66:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testResetPassword";d:0.086;s:63:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testChangeRole";d:0.008;s:65:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testActivateUser";d:0.003;s:63:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testDeleteUser";d:0.011;s:70:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddUserCustomRole";d:0.09;s:71:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddUserDefaultRole";d:0.081;s:77:"CakeDC\Users\Test\TestCase\Shell\UsersShellTest::testAddUserCustomDefaultRole";d:0.079;s:73:"CakeDC\Users\Test\TestCase\Traits\RandomStringTraitTest::testRandomString";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #0";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #1";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #2";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #3";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #4";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #5";d:0.003;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #6";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #7";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #8";d:0;s:87:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #9";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #10";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #11";d:0.001;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #12";d:0.001;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #13";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #14";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #15";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #16";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #17";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #18";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #19";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #20";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #21";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #22";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #23";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #24";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #25";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #26";d:0.001;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #27";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #28";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #29";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #30";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #31";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #32";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #33";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #34";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #35";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #36";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #37";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #38";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #39";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #40";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #41";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #42";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #43";d:0.001;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #44";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #45";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #46";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #47";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #48";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #49";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #50";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #51";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #52";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #53";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #54";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #55";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #56";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #57";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #58";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #59";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #60";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #61";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #62";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #63";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #64";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #65";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #66";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #67";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #68";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #69";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #70";d:0;s:88:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionRouteParams with data set #71";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #0";d:0.001;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #1";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #2";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #3";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #4";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #5";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #6";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #7";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #8";d:0;s:82:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #9";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #10";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #11";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #12";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #13";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #14";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #15";d:0.002;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #16";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #17";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #18";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #19";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #20";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #21";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #22";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #23";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #24";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #25";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #26";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #27";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #28";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #29";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #30";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #31";d:0.001;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #32";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #33";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #34";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #35";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #36";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #37";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #38";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #39";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #40";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #41";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #42";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #43";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #44";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #45";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #46";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #47";d:0.001;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #48";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #49";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #50";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #51";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #52";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #53";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #54";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #55";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #56";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #57";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #58";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #59";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #60";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #61";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #62";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #63";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #64";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #65";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #66";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #67";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #68";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #69";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #70";d:0;s:83:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionParams with data set #71";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #0";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #1";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #2";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #3";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #4";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #5";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #6";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #7";d:0.002;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #8";d:0;s:79:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #9";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #10";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #11";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #12";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #13";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #14";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #15";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #16";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #17";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #18";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #19";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #20";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #21";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #22";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #23";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #24";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #25";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #26";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #27";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #28";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #29";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #30";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #31";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #32";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #33";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #34";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #35";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #36";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #37";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #38";d:0.002;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #39";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #40";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #41";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #42";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #43";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #44";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #45";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #46";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #47";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #48";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #49";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #50";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #51";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #52";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #53";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #54";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #55";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #56";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #57";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #58";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #59";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #60";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #61";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #62";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #63";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #64";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #65";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #66";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #67";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #68";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #69";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #70";d:0;s:80:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testActionUrl with data set #71";d:0;s:90:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testCheckActionOnRequest with data set #0";d:0;s:90:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testCheckActionOnRequest with data set #1";d:0;s:90:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testCheckActionOnRequest with data set #2";d:0;s:90:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testCheckActionOnRequest with data set #3";d:0;s:90:"CakeDC\Users\Test\TestCase\Utility\UsersUrlTest::testCheckActionOnRequest with data set #4";d:0;s:80:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testLinkFalseWithMock";d:0.015;s:82:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testLinkAuthorizedHappy";d:0.001;s:88:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testLinkAuthorizedAllowedTrue";d:0.001;s:89:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testLinkAuthorizedAllowedFalse";d:0;s:73:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testGetRequest";d:0;s:105:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testPostLinkAuthorizedAllowedTrueLoggedAsAdmin";d:0.001;s:110:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testPostLinkAuthorizedAllowedFalseLoggedWithoutRole";d:0;s:93:"CakeDC\Users\Test\TestCase\View\Helper\AuthLinkHelperTest::testPostLinkAuthorizedAllowedFalse";d:0.001;s:65:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testLogout";d:0.007;s:81:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testLogoutDifferentMessage";d:0.002;s:76:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testLogoutWithOptions";d:0.001;s:66:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testWelcome";d:0.003;s:81:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testWelcomeNotLoggedInUser";d:0.001;s:71:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testAddReCaptcha";d:0.057;s:76:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testAddReCaptchaEmpty";d:0.001;s:77:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testAddReCaptchaScript";d:0.005;s:74:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialLoginLink";d:0.001;s:81:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialLoginTranslation";d:0.087;s:80:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialConnectLinkList";d:0.001;s:103:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialConnectLinkListIsConnectedWithFacebook";d:0.001;s:98:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialConnectLinkListSocialIsNotEnabled";d:0.001;s:117:"CakeDC\Users\Test\TestCase\View\Helper\UserHelperTest::testSocialConnectLinkListSocialEnabledButNotConfiguredProvider";d:0.001;}}} \ No newline at end of file From 77570eb4462c2966a78d79b233ded8d77335b0e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 30 Jan 2020 12:31:14 +0000 Subject: [PATCH 488/685] remove lock file not needed --- config/Migrations/schema-dump-default.lock | Bin 7938 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 config/Migrations/schema-dump-default.lock 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{ From 9a6430a15884eb02386803ee98cd08de24ee5dee Mon Sep 17 00:00:00 2001 From: Chris Hallgren Date: Thu, 30 Jan 2020 06:42:35 -0600 Subject: [PATCH 489/685] Fix correct version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc9f377fb..33d0038c6 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Versions and branches | :-------------: | :------------------------: | :--: | :---- | | 3.7 | [master](https://github.com/cakedc/users/tree/master) | 8.5.1 | stable | | 3.7 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | -| ^4.0 | [8.5](https://github.com/cakedc/users/tree/9.next) | 9.0.0 | stable | +| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.0 | stable | | ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | | 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | | 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | From 5b8ae8590b19b4d06a4736711acab59c1ca86975 Mon Sep 17 00:00:00 2001 From: Chris Hallgren Date: Thu, 30 Jan 2020 06:52:53 -0600 Subject: [PATCH 490/685] Updating Readme with correct links and 9.0 info --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d94e1e43..33d0038c6 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ Versions and branches | :-------------: | :------------------------: | :--: | :---- | | 3.7 | [master](https://github.com/cakedc/users/tree/master) | 8.5.1 | stable | | 3.7 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | -| ^3.7 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | +| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.0 | stable | +| ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | | 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | | 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | | 3.4 | [5.x](https://github.com/cakedc/users/tree/5.x) | 5.2.0 | stable | From 24708cfc629cb70e08c71c4eeb665eace7b39dd6 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 30 Jan 2020 14:39:35 -0300 Subject: [PATCH 491/685] phpstan fixes --- phpstan-baseline.neon | 175 ------------------ phpstan.neon | 4 +- src/Controller/Component/LoginComponent.php | 6 +- .../Traits/CustomUsersTableTrait.php | 3 + src/Controller/Traits/U2fTrait.php | 2 + src/Model/Entity/User.php | 7 +- 6 files changed, 16 insertions(+), 181 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index ce7a31ff2..2e679c318 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -7,11 +7,6 @@ parameters: count: 1 path: src\Controller\Component\LoginComponent.php - - - message: "#^Negated boolean expression is always false\\.$#" - count: 1 - path: src\Controller\Component\LoginComponent.php - - message: "#^Call to an undefined method Cake\\\\Controller\\\\Controller\\:\\:getUsersTable\\(\\)\\.$#" count: 1 @@ -22,31 +17,11 @@ parameters: count: 1 path: src\Controller\SocialAccountsController.php - - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\SocialAccountsController\\:\\:validateAccount\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" - count: 1 - path: src\Controller\SocialAccountsController.php - - message: "#^Call to an undefined method CakeDC\\\\Users\\\\Model\\\\Table\\\\SocialAccountsTable\\:\\:resendValidation\\(\\)\\.$#" count: 1 path: src\Controller\SocialAccountsController.php - - - message: "#^Parameter \\#1 \\$provider of method CakeDC\\\\Auth\\\\Social\\\\Service\\\\ServiceFactory\\:\\:createFromProvider\\(\\) expects string, string\\|null given\\.$#" - count: 2 - path: src\Controller\UsersController.php - - - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:linkSocial\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:callbackLinkSocial\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" - count: 2 - path: src\Controller\UsersController.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:linkSocialAccount\\(\\)\\.$#" count: 1 @@ -62,11 +37,6 @@ parameters: count: 2 path: src\Controller\UsersController.php - - - message: "#^Cannot assign offset 'secret_verified' to array\\|string\\|null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - message: "#^Parameter \\#1 \\$user of method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:onVerifyGetSecret\\(\\) expects CakeDC\\\\Users\\\\Model\\\\Entity\\\\User, array\\|string\\|null given\\.$#" count: 1 @@ -77,36 +47,11 @@ parameters: count: 3 path: src\Controller\UsersController.php - - - message: "#^Offset 'email' does not exist on array\\|string\\|null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - - - message: "#^Cannot assign offset 'id' to array\\|string\\.$#" - count: 1 - path: src\Controller\UsersController.php - - - - message: "#^Offset 'id' does not exist on array\\|string\\|null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:onPostVerifyCode\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - message: "#^Parameter \\#2 \\$user of method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:onPostVerifyCodeOkay\\(\\) expects CakeDC\\\\Users\\\\Model\\\\Entity\\\\User, array\\|string\\|null given\\.$#" count: 1 path: src\Controller\UsersController.php - - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:onPostVerifyCodeOkay\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validationPasswordConfirm\\(\\)\\.$#" count: 1 @@ -127,11 +72,6 @@ parameters: count: 2 path: src\Controller\UsersController.php - - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:requestResetPassword\\(\\) should return Cake\\\\Http\\\\Response\\|void but returns Cake\\\\Http\\\\Response\\|null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - message: "#^Parameter \\#2 \\$options of method Cake\\\\Controller\\\\Component\\\\FlashComponent\\:\\:success\\(\\) expects array, string given\\.$#" count: 1 @@ -142,11 +82,6 @@ parameters: count: 1 path: src\Controller\UsersController.php - - - message: "#^Parameter \\#1 \\$url of method Cake\\\\Controller\\\\Controller\\:\\:redirect\\(\\) expects array\\|Psr\\\\Http\\\\Message\\\\UriInterface\\|string, string\\|null given\\.$#" - count: 3 - path: src\Controller\UsersController.php - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:_getReCaptchaInstance\\(\\) should return ReCaptcha\\\\ReCaptcha but returns null\\.$#" count: 1 @@ -157,36 +92,11 @@ parameters: count: 2 path: src\Controller\UsersController.php - - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:_afterRegister\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - message: "#^Parameter \\#1 \\$object of method Cake\\\\Controller\\\\Controller\\:\\:paginate\\(\\) expects Cake\\\\ORM\\\\Query\\|Cake\\\\ORM\\\\Table\\|string\\|null, Cake\\\\Datasource\\\\RepositoryInterface given\\.$#" count: 1 path: src\Controller\UsersController.php - - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:delete\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:redirectWithQuery\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - - - message: "#^Parameter \\#1 \\$json of function json_decode expects string, array\\|string\\|null given\\.$#" - count: 2 - path: src\Controller\UsersController.php - - - - message: "#^Cannot assign offset 'id' to array\\|string\\|null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$u2f_registration\\.$#" count: 1 @@ -197,11 +107,6 @@ parameters: count: 2 path: src\Controller\UsersController.php - - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:validate\\(\\) should return Cake\\\\Http\\\\Response but returns Cake\\\\Http\\\\Response\\|null\\.$#" - count: 3 - path: src\Controller\UsersController.php - - message: "#^Method CakeDC\\\\Users\\\\Authenticator\\\\SocialPendingEmailAuthenticator\\:\\:_getReCaptchaInstance\\(\\) should return ReCaptcha\\\\ReCaptcha but returns null\\.$#" count: 1 @@ -212,11 +117,6 @@ parameters: count: 1 path: src\Identifier\SocialIdentifier.php - - - message: "#^Parameter \\#1 \\$object of function get_class expects object, Throwable\\|null given\\.$#" - count: 1 - path: src\Middleware\SocialAuthMiddleware.php - - message: "#^Parameter \\#2 \\$request of method CakeDC\\\\Users\\\\Utility\\\\UsersUrl\\:\\:checkActionOnRequest\\(\\) expects Cake\\\\Http\\\\ServerRequest, Psr\\\\Http\\\\Message\\\\ServerRequestInterface given\\.$#" count: 1 @@ -242,11 +142,6 @@ parameters: count: 1 path: src\Model\Behavior\BaseTokenBehavior.php - - - message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\BaseTokenBehavior\\:\\:_removeValidationToken\\(\\) should return Cake\\\\Datasource\\\\EntityInterface but returns Cake\\\\Datasource\\\\EntityInterface\\|false\\.$#" - count: 1 - path: src\Model\Behavior\BaseTokenBehavior.php - - message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$SocialAccounts\\.$#" count: 5 @@ -312,11 +207,6 @@ parameters: count: 1 path: src\Model\Behavior\RegisterBehavior.php - - - message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\RegisterBehavior\\:\\:validate\\(\\) should return Cake\\\\Datasource\\\\EntityInterface but returns array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" - count: 1 - path: src\Model\Behavior\RegisterBehavior.php - - message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$active\\.$#" count: 1 @@ -337,11 +227,6 @@ parameters: count: 1 path: src\Model\Behavior\RegisterBehavior.php - - - message: "#^Parameter \\#2 \\$user of method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:sendSocialValidationEmail\\(\\) expects Cake\\\\Datasource\\\\EntityInterface, array\\|Cake\\\\Datasource\\\\EntityInterface given\\.$#" - count: 1 - path: src\Model\Behavior\SocialAccountBehavior.php - - message: "#^Cannot access property \\$token on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" count: 1 @@ -372,31 +257,16 @@ parameters: count: 1 path: src\Model\Behavior\SocialAccountBehavior.php - - - message: "#^Parameter \\#1 \\$socialAccount of method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:sendSocialValidationEmail\\(\\) expects Cake\\\\Datasource\\\\EntityInterface, array\\|Cake\\\\Datasource\\\\EntityInterface given\\.$#" - count: 1 - path: src\Model\Behavior\SocialAccountBehavior.php - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\SocialAccount\\:\\:\\$active\\.$#" count: 1 path: src\Model\Behavior\SocialAccountBehavior.php - - - message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:_activateAccount\\(\\) should return Cake\\\\Datasource\\\\EntityInterface but returns Cake\\\\Datasource\\\\EntityInterface\\|false\\.$#" - count: 1 - path: src\Model\Behavior\SocialAccountBehavior.php - - message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$SocialAccounts\\.$#" count: 4 path: src\Model\Behavior\SocialBehavior.php - - - message: "#^Parameter \\#2 \\$existingUser of method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialBehavior\\:\\:_populateUser\\(\\) expects Cake\\\\Datasource\\\\EntityInterface, array\\|Cake\\\\Datasource\\\\EntityInterface\\|null given\\.$#" - count: 1 - path: src\Model\Behavior\SocialBehavior.php - - message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$isValidateEmail\\.$#" count: 1 @@ -407,56 +277,16 @@ parameters: count: 1 path: src\Model\Behavior\SocialBehavior.php - - - message: "#^PHPDoc tag @property has invalid value \\(\\\\Cake\\\\I18n\\\\Time token_expires\\)\\: Unexpected token \"token_expires\", expected TOKEN_VARIABLE at offset 167$#" - count: 1 - path: src\Model\Entity\User.php - - - - message: "#^PHPDoc tag @property has invalid value \\(array additional_data\\)\\: Unexpected token \"additional_data\", expected TOKEN_VARIABLE at offset 226$#" - count: 1 - path: src\Model\Entity\User.php - - - - message: "#^PHPDoc tag @property has invalid value \\(string token\\)\\: Unexpected token \"token\", expected TOKEN_VARIABLE at offset 201$#" - count: 1 - path: src\Model\Entity\User.php - - message: "#^Method CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\:\\:_setTos\\(\\) should return bool but returns string\\.$#" count: 1 path: src\Model\Entity\User.php - - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\:\\:\\$social_accounts\\.$#" - count: 1 - path: src\Model\Entity\User.php - - - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\:\\:\\$additional_data\\.$#" - count: 1 - path: src\Model\Entity\User.php - - - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\:\\:\\$token_expires\\.$#" - count: 1 - path: src\Model\Entity\User.php - - - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\:\\:\\$token\\.$#" - count: 1 - path: src\Model\Entity\User.php - - message: "#^Property CakeDC\\\\Users\\\\Shell\\\\UsersShell\\:\\:\\$Users \\(CakeDC\\\\Users\\\\Model\\\\Table\\\\UsersTable\\) does not accept Cake\\\\Datasource\\\\RepositoryInterface\\.$#" count: 1 path: src\Shell\UsersShell.php - - - message: "#^Cannot access property \\$role on bool\\|CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\.$#" - count: 1 - path: src\Shell\UsersShell.php - - message: "#^Cannot access property \\$username on bool\\.$#" count: 2 @@ -467,11 +297,6 @@ parameters: count: 1 path: src\Shell\UsersShell.php - - - message: "#^Method CakeDC\\\\Users\\\\Shell\\\\UsersShell\\:\\:_changeUserActive\\(\\) should return bool but returns bool\\|CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\.$#" - count: 1 - path: src\Shell\UsersShell.php - - message: "#^Call to an undefined method CakeDC\\\\Users\\\\Model\\\\Table\\\\UsersTable\\:\\:generateUniqueUsername\\(\\)\\.$#" count: 1 diff --git a/phpstan.neon b/phpstan.neon index 2f542b935..0254599fe 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,7 +2,9 @@ includes: - phpstan-baseline.neon parameters: - level: 7 + level: 6 + checkMissingIterableValueType: false + checkGenericClassInNonGenericObjectType: false autoload_files: - tests/bootstrap.php ignoreErrors: diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index 76fd358f0..eefbb97d2 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -60,6 +60,8 @@ public function handleLogin($errorOnlyPost, $redirectFailure) if ($request->is('post') || $errorOnlyPost === false) { return $this->handleFailure($redirectFailure); } + + return null; } /** @@ -157,10 +159,10 @@ protected function handlePasswordRehash($service, $user, \Cake\Http\ServerReques $indentifiersNames = (array)Configure::read('Auth.PasswordRehash.identifiers'); foreach ($indentifiersNames as $indentifierName) { /** - * @var \Authentication\PasswordHasher\PasswordHasherTrait $checker |null + * @var \Authentication\Identifier\AbstractIdentifier|null $checker */ $checker = $service->identifiers()->get($indentifierName); - if (!$checker || !$checker->needsPasswordRehash()) { + if (!$checker || method_exists($checker, 'needsPasswordRehash') && !$checker->needsPasswordRehash()) { continue; } $password = $request->getData('password'); diff --git a/src/Controller/Traits/CustomUsersTableTrait.php b/src/Controller/Traits/CustomUsersTableTrait.php index 8846d4bfb..03d6c304e 100644 --- a/src/Controller/Traits/CustomUsersTableTrait.php +++ b/src/Controller/Traits/CustomUsersTableTrait.php @@ -23,6 +23,9 @@ */ trait CustomUsersTableTrait { + /** + * @var \Cake\ORM\Table|null + */ protected $_usersTable = null; /** diff --git a/src/Controller/Traits/U2fTrait.php b/src/Controller/Traits/U2fTrait.php index 956837676..90f4151a4 100644 --- a/src/Controller/Traits/U2fTrait.php +++ b/src/Controller/Traits/U2fTrait.php @@ -148,6 +148,8 @@ public function u2fAuthenticate() $authenticateRequest = $this->createU2fLib()->getAuthenticateData([$data['registration']]); $this->getRequest()->getSession()->write('U2f.authenticateRequest', json_encode($authenticateRequest)); $this->set(compact('authenticateRequest')); + + return null; } /** diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 37f09f9bc..45e162089 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -25,9 +25,10 @@ * @property string $role * @property string $username * @property bool $is_superuser - * @property \Cake\I18n\Time token_expires - * @property string token - * @property array additional_data + * @property \Cake\I18n\Time $token_expires + * @property string $token + * @property array $additional_data + * @property \CakeDC\Users\Model\Entity\SocialAccount[] $social_accounts */ class User extends Entity { From 1c0d6633f8540607bb182a91d3d1add0bb5d988c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 30 Jan 2020 14:42:53 -0300 Subject: [PATCH 492/685] Starting integration tests structure --- composer.json | 3 +- tests/Fixture/UsersFixture.php | 4 +- .../Integration/LoginTraitIntegrationTest.php | 90 +++++++++ tests/bootstrap.php | 36 +--- tests/config/bootstrap.php | 6 +- tests/test_app/TestApp/Application.php | 50 +++++ tests/test_app/config/bootstrap.php | 2 + tests/test_app/config/routes.php | 8 + tests/test_app/templates/Error/empty | 0 tests/test_app/templates/Error/error400.php | 29 +++ tests/test_app/templates/Error/error500.php | 27 +++ tests/test_app/templates/Pages/extract.php | 37 ++++ tests/test_app/templates/Pages/home.php | 173 ++++++++++++++++++ tests/test_app/templates/Pages/page.home.php | 2 + .../templates/element/flash/default.php | 1 + .../templates/element/flash/error.php | 1 + .../test_app/templates/email/html/default.php | 7 + .../test_app/templates/email/text/default.php | 1 + tests/test_app/templates/layout/ajax.php | 1 + tests/test_app/templates/layout/default.php | 42 +++++ .../templates/layout/email/html/default.php | 13 ++ .../templates/layout/email/text/default.php | 4 + tests/test_app/templates/layout/error.php | 1 + .../test_app/templates/layout/js/default.php | 2 + .../test_app/templates/layout/rss/default.php | 17 ++ 25 files changed, 523 insertions(+), 34 deletions(-) create mode 100644 tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php create mode 100644 tests/test_app/TestApp/Application.php create mode 100644 tests/test_app/config/bootstrap.php create mode 100644 tests/test_app/config/routes.php create mode 100644 tests/test_app/templates/Error/empty create mode 100644 tests/test_app/templates/Error/error400.php create mode 100644 tests/test_app/templates/Error/error500.php create mode 100644 tests/test_app/templates/Pages/extract.php create mode 100644 tests/test_app/templates/Pages/home.php create mode 100644 tests/test_app/templates/Pages/page.home.php create mode 100644 tests/test_app/templates/element/flash/default.php create mode 100644 tests/test_app/templates/element/flash/error.php create mode 100644 tests/test_app/templates/email/html/default.php create mode 100644 tests/test_app/templates/email/text/default.php create mode 100644 tests/test_app/templates/layout/ajax.php create mode 100644 tests/test_app/templates/layout/default.php create mode 100644 tests/test_app/templates/layout/email/html/default.php create mode 100644 tests/test_app/templates/layout/email/text/default.php create mode 100644 tests/test_app/templates/layout/error.php create mode 100644 tests/test_app/templates/layout/js/default.php create mode 100644 tests/test_app/templates/layout/rss/default.php diff --git a/composer.json b/composer.json index c848d80fd..3226dfc7f 100644 --- a/composer.json +++ b/composer.json @@ -67,7 +67,8 @@ "autoload-dev": { "psr-4": { "CakeDC\\Users\\Test\\": "tests", - "CakeDC\\Users\\Test\\Fixture\\": "tests" + "CakeDC\\Users\\Test\\Fixture\\": "tests", + "TestApp\\": "tests/test_app/TestApp/" } }, "scripts": { diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index 6cbcff6a4..a16f1f936 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -1,4 +1,5 @@ '00000000-0000-0000-0000-000000000002', 'username' => 'user-2', 'email' => 'user-2@test.com', - 'password' => '12345', + //The password real value is 12345 + 'password' => '$2y$10$Nvu7ipP.z8tiIl75OdUvt.86vuG6iKMoHIOc7O7mboFI85hSyTEde', 'first_name' => 'user', 'last_name' => 'second', 'token' => '6614f65816754310a5f0553436dd89e9', diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php new file mode 100644 index 000000000..9b8a3f5c7 --- /dev/null +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -0,0 +1,90 @@ +get('/login'); + $this->assertResponseOk(); + $this->assertResponseNotContains('Username or password is incorrect'); + $this->assertResponseContains('
'); + $this->assertResponseContains('Please enter your username and password'); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains('Register'); + $this->assertResponseContains('Reset Password'); + } + + /** + * Test login action with get request + * + * @return void + */ + public function testLoginPostRequestInvalidPassword() + { + $this->post('/login', [ + 'username' => 'user-2', + 'password' => '123456789' + ]); + $this->assertResponseOk(); + $this->assertResponseContains('Username or password is incorrect'); + $this->assertResponseContains(''); + $this->assertResponseContains('Please enter your username and password'); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + } + + /** + * Test login action with get request + * + * @return void + */ + public function testLoginPostRequestRightPassword() + { + $this->enableRetainFlashMessages(); + $this->post('/login', [ + 'username' => 'user-2', + 'password' => '12345' + ]); + $this->assertRedirect('/'); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 36988a2b0..c131ed5fd 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -40,12 +40,14 @@ define('DS', DIRECTORY_SEPARATOR); } define('ROOT', $root); -define('APP_DIR', 'App'); +define('APP_DIR', 'TestApp'); define('WEBROOT_DIR', 'webroot'); -define('APP', ROOT . '/tests/App/'); -define('CONFIG', ROOT . '/tests/config/'); -define('WWW_ROOT', ROOT . DS . WEBROOT_DIR . DS); define('TESTS', ROOT . DS . 'tests' . DS); +define('TEST_APP', TESTS . 'test_app' . DS); +define('APP', TEST_APP . 'TestApp' . DS); +define('WWW_ROOT', TEST_APP . 'webroot' . DS); +define('CONFIG', TEST_APP . 'config' . DS); + define('TMP', ROOT . DS . 'tmp' . DS); define('LOGS', TMP . 'logs' . DS); define('CACHE', TMP . 'cache' . DS); @@ -90,32 +92,6 @@ 'defaults' => 'php', ]); -Configure::write('App', [ - 'namespace' => 'Users\Test\App', - 'encoding' => 'UTF-8', - 'base' => false, - 'baseUrl' => false, - 'dir' => 'src', - 'webroot' => WEBROOT_DIR, - 'wwwRoot' => WWW_ROOT, - 'fullBaseUrl' => 'http://localhost', - 'imageBaseUrl' => 'img/', - 'jsBaseUrl' => 'js/', - 'cssBaseUrl' => 'css/', - 'paths' => [ - 'plugins' => [dirname(APP) . DS . 'plugins' . DS], - 'templates' => [dirname(APP) . 'templates' . DS], - ], -]); - -// \Cake\Core\Configure::write('App.paths.templates', [ - // APP . 'Template/', -// ]); - - -//init router -\Cake\Routing\Router::reload(); - Plugin::getCollection()->add(new \CakeDC\Users\Plugin([ 'path' => dirname(dirname(__FILE__)) . DS, 'routes' => true, diff --git a/tests/config/bootstrap.php b/tests/config/bootstrap.php index 41777986e..7e91559c4 100644 --- a/tests/config/bootstrap.php +++ b/tests/config/bootstrap.php @@ -14,7 +14,7 @@ class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\AppController'); Configure::write('App', [ - 'namespace' => 'Users\Test\App', + 'namespace' => 'TestApp', 'encoding' => 'UTF-8', 'base' => false, 'baseUrl' => false, @@ -27,9 +27,11 @@ class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\Ap 'cssBaseUrl' => 'css/', 'paths' => [ 'plugins' => [dirname(APP) . DS . 'plugins' . DS], - 'templates' => [dirname(APP) . 'templates' . DS], + 'templates' => [dirname(APP) . DS . 'templates' . DS], ], ]); +\Cake\Utility\Security::setSalt('yoyz186elmi66ab9pz4imbb3tgy9vnsgsfgwe2r8tyxbbfdygu9e09tlxyg8p7dq'); + if (!getenv('db_dsn')) { putenv('db_dsn=sqlite:///:memory:'); } diff --git a/tests/test_app/TestApp/Application.php b/tests/test_app/TestApp/Application.php new file mode 100644 index 000000000..62137d97e --- /dev/null +++ b/tests/test_app/TestApp/Application.php @@ -0,0 +1,50 @@ +addPlugin(Plugin::class); + } + + /** + * Setup the middleware queue your application will use. + * + * @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to setup. + * @return \Cake\Http\MiddlewareQueue The updated middleware queue. + */ + public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue + { + $middlewareQueue + ->add(new AssetMiddleware([ + 'cacheTime' => Configure::read('Asset.cacheTime'), + ])) + ->add(new RoutingMiddleware($this)); + + return $middlewareQueue; + } +} diff --git a/tests/test_app/config/bootstrap.php b/tests/test_app/config/bootstrap.php new file mode 100644 index 000000000..5ff14cf06 --- /dev/null +++ b/tests/test_app/config/bootstrap.php @@ -0,0 +1,2 @@ +fallbacks(); +}); diff --git a/tests/test_app/templates/Error/empty b/tests/test_app/templates/Error/empty new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_app/templates/Error/error400.php b/tests/test_app/templates/Error/error400.php new file mode 100644 index 000000000..840e81bf6 --- /dev/null +++ b/tests/test_app/templates/Error/error400.php @@ -0,0 +1,29 @@ + +

+

+ : + '{$url}'" + ) ?> +

+element('exception_stack_trace'); +endif; +?> diff --git a/tests/test_app/templates/Error/error500.php b/tests/test_app/templates/Error/error500.php new file mode 100644 index 000000000..f522672f1 --- /dev/null +++ b/tests/test_app/templates/Error/error500.php @@ -0,0 +1,27 @@ + +

+

+ : + +

+element('auto_table_warning'); + echo $this->element('exception_stack_trace'); +endif; +?> diff --git a/tests/test_app/templates/Pages/extract.php b/tests/test_app/templates/Pages/extract.php new file mode 100644 index 000000000..443fccb51 --- /dev/null +++ b/tests/test_app/templates/Pages/extract.php @@ -0,0 +1,37 @@ + 10]; + +// Plural +echo __n('You have %d new message.', 'You have %d new messages.', $count); +echo __n('You deleted %d message.', 'You deleted %d messages.', $messages['count']); + +// Domain Plural +echo __dn('domain', 'You have %d new message (domain).', 'You have %d new messages (domain).', '10'); +echo __dn('domain', 'You deleted %d message (domain).', 'You deleted %d messages (domain).', $messages['count']); + +// Duplicated Message +echo __('Editing this Page'); +echo __('You have %d new message.'); + +// Contains quotes +echo __('double "quoted"'); +echo __("single 'quoted'"); + +// Contains no string like a variable or a function or ... +echo __($count); + +// Multiline +__('Hot features!' + . "\n - No Configuration:" + . ' Set-up the database and let the magic begin' + . "\n - Extremely Simple:" + . ' Just look at the name...It\'s Cake' + . "\n - Active, Friendly Community:" + . ' Join us #cakephp on IRC. We\'d love to help you get started'); + +// Context +echo __x('mail', 'letter'); + +// Duplicated message with different context +echo __x('alphabet', 'letter'); diff --git a/tests/test_app/templates/Pages/home.php b/tests/test_app/templates/Pages/home.php new file mode 100644 index 000000000..0d8fca5d7 --- /dev/null +++ b/tests/test_app/templates/Pages/home.php @@ -0,0 +1,173 @@ + +

+

+ Read the changelog +

+ + +

+ URL rewriting is not properly configured on your server. + 1) Help me configure it + 2) I don't / can't use URL rewriting +

+ + +

+=')): ?> + Your version of PHP is 5.4.3 or higher + + Your version of PHP is too low. You need PHP 5.4.3 or higher to use CakePHP. + +

+ +

+ + Your version of PHP has mbstring extension loaded. + + Your version of PHP does NOT have the mbstring extension loaded. + +

+ +

+ + Your tmp directory is writable. + + Your tmp directory is NOT writable. + +

+ +

+config() : false; +if (!empty($settings)): ?> + The Engine is being used for core caching. To change the config edit APP/Config/cache.php + + Your cache is NOT working. Please check the settings in APP/Config/cache.php + +

+ +

+ + Your datasources configuration file is present. + + + Your datasources configuration file is NOT present. +
+ Rename APP/Config/datasources.default.php to APP/Config/datasources.php +
+ +

+ + +

' + PCRE has not been compiled with Unicode support.'; +
+ Recompile PCRE with Unicode support by adding --enable-unicode-properties when configuring +

+ + +

+ + DebugKit plugin is present + + '; + DebugKit is not installed. It will help you inspect and debug different aspects of your application. +
+ You can install it from Html->link('GitHub', 'https://github.com/cakephp/debug_kit'); ?> +
+ +

+ +

Editing this Page

+

+To change the content of this page, edit: APP/View/Pages/home.ctp.
+To change its layout, edit: APP/View/Layout/default.ctp.
+You can also add some CSS styles for your pages at: APP/webroot/css.; +

+ +

Getting Started

+

+ Html->link( + 'New CakePHP 3.0 Docs', + 'https://book.cakephp.org/4/en/', + ['target' => '_blank', 'escape' => false] + ); + ?> +

+

+ Html->link( + 'The 15 min Blog Tutorial', + 'https://book.cakephp.org/4/en/getting-started.html#blog-tutorial', + ['target' => '_blank', 'escape' => false] + ); + ?> +

+ +

Official Plugins

+

+

    +
  • + Html->link('DebugKit', 'https://github.com/cakephp/debug_kit') ?>: + provides a debugging toolbar and enhanced debugging tools for CakePHP application. +
  • +
  • + Html->link('Localized', 'https://github.com/cakephp/localized') ?>: + contains various localized validation classes and translations for specific countries +
  • +
+

+ +

More about CakePHP

+

+CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC. +

+

+Our primary goal is to provide a structured framework that enables PHP users at all levels to rapidly develop robust web applications, without any loss to flexibility. +

+ + diff --git a/tests/test_app/templates/Pages/page.home.php b/tests/test_app/templates/Pages/page.home.php new file mode 100644 index 000000000..46f877f38 --- /dev/null +++ b/tests/test_app/templates/Pages/page.home.php @@ -0,0 +1,2 @@ +Empty page with a dot in the filename. +Used to test plugin.view and missing plugins. diff --git a/tests/test_app/templates/element/flash/default.php b/tests/test_app/templates/element/flash/default.php new file mode 100644 index 000000000..6e581ce22 --- /dev/null +++ b/tests/test_app/templates/element/flash/default.php @@ -0,0 +1 @@ +
diff --git a/tests/test_app/templates/element/flash/error.php b/tests/test_app/templates/element/flash/error.php new file mode 100644 index 000000000..6e581ce22 --- /dev/null +++ b/tests/test_app/templates/element/flash/error.php @@ -0,0 +1 @@ +
diff --git a/tests/test_app/templates/email/html/default.php b/tests/test_app/templates/email/html/default.php new file mode 100644 index 000000000..57985e141 --- /dev/null +++ b/tests/test_app/templates/email/html/default.php @@ -0,0 +1,7 @@ + ' . $line . '

'; +endforeach; +?> diff --git a/tests/test_app/templates/email/text/default.php b/tests/test_app/templates/email/text/default.php new file mode 100644 index 000000000..90e6d7909 --- /dev/null +++ b/tests/test_app/templates/email/text/default.php @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/test_app/templates/layout/ajax.php b/tests/test_app/templates/layout/ajax.php new file mode 100644 index 000000000..2f16ebc45 --- /dev/null +++ b/tests/test_app/templates/layout/ajax.php @@ -0,0 +1 @@ + diff --git a/tests/test_app/templates/layout/default.php b/tests/test_app/templates/layout/default.php new file mode 100644 index 000000000..d576f14d1 --- /dev/null +++ b/tests/test_app/templates/layout/default.php @@ -0,0 +1,42 @@ +loadHelper('Html'); + +$cakeDescription = 'My Test App'; +?> + + + + Html->charset(); ?> + + <?= $cakeDescription ?>: + <?= $this->fetch('title'); ?> + + Html->meta('icon'); + + echo $this->Html->css('cake.generic'); + + echo $this->fetch('script'); + ?> + + +
+ +
+ + fetch('content'); ?> + +
+ +
+ + diff --git a/tests/test_app/templates/layout/email/html/default.php b/tests/test_app/templates/layout/email/html/default.php new file mode 100644 index 000000000..809f44c2b --- /dev/null +++ b/tests/test_app/templates/layout/email/html/default.php @@ -0,0 +1,13 @@ + + + + + <?= $this->fetch('title'); ?> + + + + fetch('content'); ?> + +

This email was sent using the CakePHP Framework

+ + diff --git a/tests/test_app/templates/layout/email/text/default.php b/tests/test_app/templates/layout/email/text/default.php new file mode 100644 index 000000000..1f8162711 --- /dev/null +++ b/tests/test_app/templates/layout/email/text/default.php @@ -0,0 +1,4 @@ + +fetch('content'); ?> + +This email was sent using the CakePHP Framework, https://cakephp.org. \ No newline at end of file diff --git a/tests/test_app/templates/layout/error.php b/tests/test_app/templates/layout/error.php new file mode 100644 index 000000000..3c56766ec --- /dev/null +++ b/tests/test_app/templates/layout/error.php @@ -0,0 +1 @@ +fetch('content'); ?> diff --git a/tests/test_app/templates/layout/js/default.php b/tests/test_app/templates/layout/js/default.php new file mode 100644 index 000000000..77f86d94f --- /dev/null +++ b/tests/test_app/templates/layout/js/default.php @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/tests/test_app/templates/layout/rss/default.php b/tests/test_app/templates/layout/rss/default.php new file mode 100644 index 000000000..b92cd3069 --- /dev/null +++ b/tests/test_app/templates/layout/rss/default.php @@ -0,0 +1,17 @@ +Rss->header(); + +if (!isset($channel)) { + $channel = []; +} +if (!isset($channel['title'])) { + $channel['title'] = $this->fetch('title'); +} + +echo $this->Rss->document( + $this->Rss->channel( + [], $channel, $this->fetch('content') + ) +); + +?> From de505d33d0b1b43487d9fa5d6c7535ea75690785 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 30 Jan 2020 15:32:13 -0300 Subject: [PATCH 493/685] Making sure config/users.php from application is loaded --- .../Integration/LoginTraitIntegrationTest.php | 3 +- tests/bootstrap.php | 12 ++++++ tests/config/bootstrap.php | 10 ----- tests/test_app/TestApp/Application.php | 9 +++++ tests/test_app/config/routes.php | 7 ++-- tests/test_app/config/users.php | 5 +++ tests/test_app/templates/Pages/extract.php | 37 ------------------- tests/test_app/templates/Pages/page.home.php | 2 - 8 files changed, 30 insertions(+), 55 deletions(-) create mode 100644 tests/test_app/config/users.php delete mode 100644 tests/test_app/templates/Pages/extract.php delete mode 100644 tests/test_app/templates/Pages/page.home.php diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index 9b8a3f5c7..e257469bb 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -15,7 +15,6 @@ use Cake\Core\Configure; -use Cake\ORM\TableRegistry; use Cake\TestSuite\IntegrationTestTrait; use Cake\TestSuite\TestCase; @@ -85,6 +84,6 @@ public function testLoginPostRequestRightPassword() 'username' => 'user-2', 'password' => '12345' ]); - $this->assertRedirect('/'); + $this->assertRedirect('/pages/home'); } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index c131ed5fd..53e64f274 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -100,6 +100,18 @@ require $root . '/config/bootstrap.php'; } + +if (!getenv('db_dsn')) { + putenv('db_dsn=sqlite:///:memory:'); +} + +Cake\Datasource\ConnectionManager::setConfig('test', [ + 'url' => getenv('db_dsn'), + 'timezone' => 'UTC', +]); + +class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\AppController'); + $app = new \CakeDC\Users\Test\TestApplication(__DIR__ . DS . 'config'); $app->bootstrap(); $app->pluginBootstrap(); diff --git a/tests/config/bootstrap.php b/tests/config/bootstrap.php index 7e91559c4..debb45b25 100644 --- a/tests/config/bootstrap.php +++ b/tests/config/bootstrap.php @@ -11,8 +11,6 @@ use Cake\Core\Configure; -class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\AppController'); - Configure::write('App', [ 'namespace' => 'TestApp', 'encoding' => 'UTF-8', @@ -32,11 +30,3 @@ class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\Ap ]); \Cake\Utility\Security::setSalt('yoyz186elmi66ab9pz4imbb3tgy9vnsgsfgwe2r8tyxbbfdygu9e09tlxyg8p7dq'); -if (!getenv('db_dsn')) { - putenv('db_dsn=sqlite:///:memory:'); -} - -Cake\Datasource\ConnectionManager::setConfig('test', [ - 'url' => getenv('db_dsn'), - 'timezone' => 'UTC', -]); diff --git a/tests/test_app/TestApp/Application.php b/tests/test_app/TestApp/Application.php index 62137d97e..79d8bda19 100644 --- a/tests/test_app/TestApp/Application.php +++ b/tests/test_app/TestApp/Application.php @@ -31,6 +31,15 @@ public function bootstrap(): void $this->addPlugin(Plugin::class); } + /** + * @inheritDoc + */ + public function pluginBootstrap(): void + { + Configure::write('Users.config', ['users']); + parent::pluginBootstrap(); + } + /** * Setup the middleware queue your application will use. * diff --git a/tests/test_app/config/routes.php b/tests/test_app/config/routes.php index a834e14fd..589cc21ad 100644 --- a/tests/test_app/config/routes.php +++ b/tests/test_app/config/routes.php @@ -1,8 +1,7 @@ fallbacks(); -}); +$routes->setRouteClass(DashedRoute::class); + diff --git a/tests/test_app/config/users.php b/tests/test_app/config/users.php new file mode 100644 index 000000000..61fff598c --- /dev/null +++ b/tests/test_app/config/users.php @@ -0,0 +1,5 @@ + '/pages/home', +]; diff --git a/tests/test_app/templates/Pages/extract.php b/tests/test_app/templates/Pages/extract.php deleted file mode 100644 index 443fccb51..000000000 --- a/tests/test_app/templates/Pages/extract.php +++ /dev/null @@ -1,37 +0,0 @@ - 10]; - -// Plural -echo __n('You have %d new message.', 'You have %d new messages.', $count); -echo __n('You deleted %d message.', 'You deleted %d messages.', $messages['count']); - -// Domain Plural -echo __dn('domain', 'You have %d new message (domain).', 'You have %d new messages (domain).', '10'); -echo __dn('domain', 'You deleted %d message (domain).', 'You deleted %d messages (domain).', $messages['count']); - -// Duplicated Message -echo __('Editing this Page'); -echo __('You have %d new message.'); - -// Contains quotes -echo __('double "quoted"'); -echo __("single 'quoted'"); - -// Contains no string like a variable or a function or ... -echo __($count); - -// Multiline -__('Hot features!' - . "\n - No Configuration:" - . ' Set-up the database and let the magic begin' - . "\n - Extremely Simple:" - . ' Just look at the name...It\'s Cake' - . "\n - Active, Friendly Community:" - . ' Join us #cakephp on IRC. We\'d love to help you get started'); - -// Context -echo __x('mail', 'letter'); - -// Duplicated message with different context -echo __x('alphabet', 'letter'); diff --git a/tests/test_app/templates/Pages/page.home.php b/tests/test_app/templates/Pages/page.home.php deleted file mode 100644 index 46f877f38..000000000 --- a/tests/test_app/templates/Pages/page.home.php +++ /dev/null @@ -1,2 +0,0 @@ -Empty page with a dot in the filename. -Used to test plugin.view and missing plugins. From c16283ab38b170e0418cf664157020745181fef8 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 30 Jan 2020 15:36:54 -0300 Subject: [PATCH 494/685] Making sure user is redirected to login --- .../Integration/LoginTraitIntegrationTest.php | 11 +++++++++++ tests/test_app/config/routes.php | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index e257469bb..16b77f824 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -31,6 +31,17 @@ class LoginTraitIntegrationTest extends TestCase 'plugin.CakeDC/Users.Users', ]; + /** + * Test login action with get request + * + * @return void + */ + public function testRedirectToLogin() + { + $this->get('/pages/home'); + $this->assertRedirect('/login?redirect=http%3A%2F%2Flocalhost%2Fpages%2Fhome'); + } + /** * Test login action with get request * diff --git a/tests/test_app/config/routes.php b/tests/test_app/config/routes.php index 589cc21ad..06073b99f 100644 --- a/tests/test_app/config/routes.php +++ b/tests/test_app/config/routes.php @@ -5,3 +5,19 @@ $routes->setRouteClass(DashedRoute::class); +$routes->scope('/', function (RouteBuilder $builder) { + /** + * Connect catchall routes for all controllers. + * + * The `fallbacks` method is a shortcut for + * + * ``` + * $builder->connect('/:controller', ['action' => 'index']); + * $builder->connect('/:controller/:action/*', []); + * ``` + * + * You can remove these routes once you've connected the + * routes you want in your application. + */ + $builder->fallbacks(); +}); From b9d2029a11706ed15f30bf9f43fbe9d42431d478 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 30 Jan 2020 15:54:56 -0300 Subject: [PATCH 495/685] Testing logout --- .../Integration/LoginTraitIntegrationTest.php | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index 16b77f824..43e019e5b 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -13,8 +13,7 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits\Integration; - -use Cake\Core\Configure; +use Cake\ORM\TableRegistry; use Cake\TestSuite\IntegrationTestTrait; use Cake\TestSuite\TestCase; @@ -31,6 +30,21 @@ class LoginTraitIntegrationTest extends TestCase 'plugin.CakeDC/Users.Users', ]; + /** + * Sets up the session as a logged in user for an user with id $id + * + * @param $id + * @return void + */ + public function loginAsUserId($id) + { + $user = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users') + ->get($id); + + $this->session(['Auth' => $user]); + } + /** * Test login action with get request * @@ -97,4 +111,27 @@ public function testLoginPostRequestRightPassword() ]); $this->assertRedirect('/pages/home'); } + + /** + * Test logout action + * + * @return void + */ + public function testLogout() + { + $this->loginAsUserId('00000000-0000-0000-0000-000000000002'); + $this->get('/logout'); + $this->assertRedirect('/login'); + } + + /** + * Test logout action + * + * @return void + */ + public function testLogoutNoUser() + { + $this->get('/logout'); + $this->assertRedirect('/login'); + } } From 18bf7703c7d97a5222d258f09c97c2ca8d3a3111 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 30 Jan 2020 16:52:49 -0300 Subject: [PATCH 496/685] Register form should require confirm password --- templates/Users/register.php | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/Users/register.php b/templates/Users/register.php index 3ab7156ba..e82673b67 100644 --- a/templates/Users/register.php +++ b/templates/Users/register.php @@ -21,6 +21,7 @@ echo $this->Form->control('email', ['label' => __d('cake_d_c/users', 'Email')]); echo $this->Form->control('password', ['label' => __d('cake_d_c/users', 'Password')]); echo $this->Form->control('password_confirm', [ + 'required' => true, 'type' => 'password', 'label' => __d('cake_d_c/users', 'Confirm password') ]); From d03ecfee8e6c16bcde95271880d75a16760b93eb Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 30 Jan 2020 16:53:42 -0300 Subject: [PATCH 497/685] Account validation should check if token is not empty to query --- src/Model/Behavior/RegisterBehavior.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index aba0b5a2a..891b13566 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -84,10 +84,10 @@ public function register($user, $data, $options) */ public function validate($token, $callback = null) { - $user = $this->_table->find() + $user = $token ? $this->_table->find() ->select(['token_expires', 'id', 'active', 'token']) ->where(['token' => $token]) - ->first(); + ->first() : null; if (empty($user)) { throw new UserNotFoundException(__d('cake_d_c/users', "User not found for the given token and email.")); } From a351e8767ce9ca0618b924b4ef852739c74e2c9e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 30 Jan 2020 16:54:00 -0300 Subject: [PATCH 498/685] Integration test for register --- .../RegisterTraitIntegrationTest.php | 143 ++++++++++++++++++ tests/config/bootstrap.php | 11 ++ 2 files changed, 154 insertions(+) create mode 100644 tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php diff --git a/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php new file mode 100644 index 000000000..24384d50e --- /dev/null +++ b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php @@ -0,0 +1,143 @@ +get('/register'); + $this->assertResponseOk(); + $this->assertResponseContains(''); + $this->assertResponseContains('Add User'); + $this->assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + } + + /** + * Test register action + * + * @return void + */ + public function testRegisterPostWithErrors() + { + $this->enableRetainFlashMessages(); + $this->enableSecurityToken(); + $this->enableCsrfToken(); + $data = [ + 'username' => 'user1', + 'email' => 'use1sample@example.com', + 'password' => '23423423', + 'password_confirm' => '11', + 'first_name' => '', + 'last_name' => '', + 'tos' => '0' + ]; + $this->post('/register', $data); + $this->assertResponseOk(); + $this->assertFlashMessage('The user could not be saved'); + $this->assertResponseNotContains('The user could not be saved'); + $this->assertResponseContains(''); + $this->assertResponseContains('Add User'); + $this->assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains('assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + } + + /** + * Test register action + * + * @return void + */ + public function testRegisterPostOkay() + { + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->assertFalse($Table->exists(['username' => 'user1'])); + $this->enableRetainFlashMessages(); + $this->enableSecurityToken(); + $this->enableCsrfToken(); + $data = [ + 'username' => 'user1', + 'email' => 'use1sample@example.com', + 'password' => '123456', + 'password_confirm' => '123456', + 'first_name' => '', + 'last_name' => '', + 'tos' => '0' + ]; + $this->post('/register', $data); + $this->assertRedirect('/login'); + $this->assertFlashMessage('Please validate your account before log in'); + $user = $Table->find()->where(['username' => 'user1'])->firstOrFail(); + $this->assertFalse($user->active); + + //Validate email + $this->assertNotEmpty($user['token']); + $url = '/users/validate-email/' . $user['token']; + $this->get($url); + $this->assertRedirect('/login'); + $this->assertFlashMessage('User account validated successfully'); + + //If access again get error + $this->get($url); + $this->assertRedirect('/login'); + $this->assertFlashMessage('Token already expired'); + } + + /** + * Test /users/validate-email without token + * + * @throws \Throwable + */ + public function testValidateEmailNoToken() + { + $this->get('/users/validate-email'); + $this->assertRedirect('/login'); + $this->assertFlashMessage('Invalid token or user account already validated'); + } +} diff --git a/tests/config/bootstrap.php b/tests/config/bootstrap.php index debb45b25..a46ff25c2 100644 --- a/tests/config/bootstrap.php +++ b/tests/config/bootstrap.php @@ -28,5 +28,16 @@ 'templates' => [dirname(APP) . DS . 'templates' . DS], ], ]); +\Cake\Mailer\TransportFactory::setConfig([ + 'default' => [ + 'className' => \Cake\Mailer\Transport\DebugTransport::class, + ], +]); +\Cake\Mailer\Email::setConfig([ + 'default' => [ + 'transport' => 'default', + 'from' => 'you@localhost', + ], +]); \Cake\Utility\Security::setSalt('yoyz186elmi66ab9pz4imbb3tgy9vnsgsfgwe2r8tyxbbfdygu9e09tlxyg8p7dq'); From f4fb73be2b71e27744b005480ac55aef0ea895df Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 11:05:55 -0300 Subject: [PATCH 499/685] Integration tests working with Security component --- .../Traits/Integration/RegisterTraitIntegrationTest.php | 2 -- tests/bootstrap.php | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php index 24384d50e..a4683d39e 100644 --- a/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php @@ -62,7 +62,6 @@ public function testRegisterPostWithErrors() { $this->enableRetainFlashMessages(); $this->enableSecurityToken(); - $this->enableCsrfToken(); $data = [ 'username' => 'user1', 'email' => 'use1sample@example.com', @@ -100,7 +99,6 @@ public function testRegisterPostOkay() $this->assertFalse($Table->exists(['username' => 'user1'])); $this->enableRetainFlashMessages(); $this->enableSecurityToken(); - $this->enableCsrfToken(); $data = [ 'username' => 'user1', 'email' => 'use1sample@example.com', diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 53e64f274..4e16bdba3 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -115,3 +115,4 @@ class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\Ap $app = new \CakeDC\Users\Test\TestApplication(__DIR__ . DS . 'config'); $app->bootstrap(); $app->pluginBootstrap(); +session_id('cli'); From 2c47f9fedeef1a338a6e8b6e1dfad76be53e5fb3 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 17:17:59 -0300 Subject: [PATCH 500/685] Integration test should redirect to otp or utf enabled --- .../Integration/LoginTraitIntegrationTest.php | 78 ++++++++++++++++++- tests/test_app/TestApp/Application.php | 2 + tests/test_app/config/users.php | 7 ++ 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index 43e019e5b..097558630 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -13,6 +13,8 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits\Integration; +use Cake\Core\Configure; +use Cake\Event\EventManager; use Cake\ORM\TableRegistry; use Cake\TestSuite\IntegrationTestTrait; use Cake\TestSuite\TestCase; @@ -61,8 +63,12 @@ public function testRedirectToLogin() * * @return void */ - public function testLoginGetRequest() + public function testLoginGetRequestNoSocialLogin() { + EventManager::instance()->on('TestApp.afterPluginBootstrap', function() { + Configure::write(['Users.Social.login' => false]); + }); + $this->get('/login'); $this->assertResponseOk(); $this->assertResponseNotContains('Username or password is incorrect'); @@ -74,6 +80,12 @@ public function testLoginGetRequest() $this->assertResponseContains(''); $this->assertResponseContains('Register'); $this->assertResponseContains('Reset Password'); + + $this->assertResponseNotContains('auth/facebook'); + $this->assertResponseNotContains('auth/twitter'); + $this->assertResponseNotContains('auth/google'); + $this->assertResponseNotContains('auth/cognito'); + $this->assertResponseNotContains('auth/amazon'); } /** @@ -81,6 +93,32 @@ public function testLoginGetRequest() * * @return void */ + public function testLoginGetRequest() + { + $this->get('/login'); + $this->assertResponseOk(); + $this->assertResponseNotContains('Username or password is incorrect'); + $this->assertResponseContains(''); + $this->assertResponseContains('Please enter your username and password'); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains('Register'); + $this->assertResponseContains('Reset Password'); + + $this->assertResponseContains('Sign in with Facebook'); + $this->assertResponseContains('Sign in with Twitter'); + $this->assertResponseContains('Sign in with Google'); + $this->assertResponseNotContains('/auth/cognito'); + $this->assertResponseNotContains('/auth/amazon'); + } + + /** + * Test login action with post request + * + * @return void + */ public function testLoginPostRequestInvalidPassword() { $this->post('/login', [ @@ -98,7 +136,7 @@ public function testLoginPostRequestInvalidPassword() } /** - * Test login action with get request + * Test login action with post request * * @return void */ @@ -112,6 +150,42 @@ public function testLoginPostRequestRightPassword() $this->assertRedirect('/pages/home'); } + /** + * Test login action with post request + * + * @return void + */ + public function testLoginPostRequestRightPasswordIsEnabledOTP() + { + EventManager::instance()->on('TestApp.afterPluginBootstrap', function() { + Configure::write(['OneTimePasswordAuthenticator.login' => true]); + }); + $this->enableRetainFlashMessages(); + $this->post('/login', [ + 'username' => 'user-2', + 'password' => '12345' + ]); + $this->assertRedirect('/verify'); + } + + /** + * Test login action with post request + * + * @return void + */ + public function testLoginPostRequestRightPasswordIsEnabledU2f() + { + EventManager::instance()->on('TestApp.afterPluginBootstrap', function() { + Configure::write(['U2f.enabled' => true]); + }); + $this->enableRetainFlashMessages(); + $this->post('/login', [ + 'username' => 'user-2', + 'password' => '12345' + ]); + $this->assertRedirect('/users/u2f'); + } + /** * Test logout action * diff --git a/tests/test_app/TestApp/Application.php b/tests/test_app/TestApp/Application.php index 79d8bda19..0184d175c 100644 --- a/tests/test_app/TestApp/Application.php +++ b/tests/test_app/TestApp/Application.php @@ -21,6 +21,7 @@ class Application extends BaseApplication { + /** * @inheritDoc */ @@ -38,6 +39,7 @@ public function pluginBootstrap(): void { Configure::write('Users.config', ['users']); parent::pluginBootstrap(); + $this->dispatchEvent('TestApp.afterPluginBootstrap'); } /** diff --git a/tests/test_app/config/users.php b/tests/test_app/config/users.php index 61fff598c..77ecdc76a 100644 --- a/tests/test_app/config/users.php +++ b/tests/test_app/config/users.php @@ -1,5 +1,12 @@ true, 'Auth.AuthenticationComponent.loginRedirect' => '/pages/home', + 'OAuth.providers.facebook.options.clientId' => '1010101010101010', + 'OAuth.providers.facebook.options.clientSecret' => 'ABABABABABABABABA', + 'OAuth.providers.twitter.options.clientId' => 'QWERTY0009', + 'OAuth.providers.twitter.options.clientSecret' => '999988899', + 'OAuth.providers.google.options.clientId' => '0000000990909090', + 'OAuth.providers.google.options.clientSecret'=> '1565464559789798', ]; From 95208c895592aa5854f015b78c0720cbdb4f2bcf Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 17:59:53 -0300 Subject: [PATCH 501/685] Integration test for password reset --- templates/Users/request_reset_password.php | 17 ++- ...PasswordManagementTraitIntegrationTest.php | 114 ++++++++++++++++++ 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php diff --git a/templates/Users/request_reset_password.php b/templates/Users/request_reset_password.php index ccd7c4264..cde49a009 100644 --- a/templates/Users/request_reset_password.php +++ b/templates/Users/request_reset_password.php @@ -1,8 +1,23 @@ +
Flash->render('auth') ?> Form->create($user) ?>
- + Form->control('reference') ?>
Form->button(__d('cake_d_c/users', 'Submit')); ?> diff --git a/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php new file mode 100644 index 000000000..d44d053cf --- /dev/null +++ b/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php @@ -0,0 +1,114 @@ +get('/users/request-reset-password'); + $this->assertResponseOk(); + $this->assertResponseContains('Please enter your email or username to reset your password'); + $this->assertResponseContains(''); + } + + /** + * Test login action with post request + * + * @return void + */ + public function testRequestResetPasswordPostValidEmail() + { + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $userBefore = $Table->find()->where(['email' => '4@example.com'])->firstOrFail(); + $this->assertEquals('token-4', $userBefore->token); + $this->enableRetainFlashMessages(); + $this->enableSecurityToken(); + $data = [ + 'reference' => '4@example.com', + ]; + $this->post('/users/request-reset-password', $data); + $this->assertRedirect('/login'); + $this->assertFlashMessage('Please check your email to continue with password reset process'); + $userAfter = $Table->find()->where(['email' => '4@example.com'])->firstOrFail(); + $this->assertNotEquals('token-4', $userAfter->token); + $this->assertNotEmpty($userAfter->token); + + $this->get("/users/reset-password/{$userAfter->token}"); + $this->assertRedirect('/users/change-password'); + + $fieldName = Configure::read('Users.Key.Session.resetPasswordUserId'); + $this->assertSession($userAfter->id , $fieldName); + $this->session([ + $fieldName => $userAfter->id + ]); + $this->get('/users/change-password'); + $this->assertResponseOk(); + + $this->assertResponseContains(''); + $this->assertResponseContains('Please enter the new password'); + $this->assertResponseContains('assertResponseContains('assertResponseContains(''); + + $this->post('/users/change-password', [ + 'password' => '9080706050', + 'password_confirm' => '9080706050' + ]); + $this->assertRedirect('/login'); + $this->assertFlashMessage('Password has been changed successfully'); + } + + /** + * Test login action with post request + * + * @return void + */ + public function testRequestResetPasswordPostInvalidEmail() + { + $email = 'someother.un@example.com'; + $Table = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $this->assertFalse($Table->exists(['email' => $email])); + $this->enableRetainFlashMessages(); + $this->enableSecurityToken(); + $data = [ + 'reference' => $email, + ]; + $this->post('/users/request-reset-password', $data); + $this->assertResponseOk(); + $this->assertFlashMessage('User someother.un@example.com was not found'); + } +} From 15f423fa1fab643dc12ff26aecf37e87701babb3 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 18:15:27 -0300 Subject: [PATCH 502/685] Integration test for profile --- .../ProfileTraitIntegrationTest.php | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php diff --git a/tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php new file mode 100644 index 000000000..75e6403ba --- /dev/null +++ b/tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php @@ -0,0 +1,80 @@ +get('CakeDC/Users.Users') + ->get('00000000-0000-0000-0000-000000000001'); + + $this->session(['Auth' => $user]); + $this->get('/profile'); + $this->assertResponseOk(); + $this->assertResponseContains('Change Password'); + $this->assertResponseContains('first1 last1'); + $this->assertResponseContains('user-1'); + $this->assertResponseContains('user-1@test.com'); + $this->assertResponseContains('Connected with Facebook'); + $this->assertResponseNotContains('Connect with Facebook'); + $this->assertResponseNotContains('/link-social/facebook'); + $this->assertResponseContains('Connected with Twitter'); + $this->assertResponseNotContains('Connect with Twitter'); + $this->assertResponseNotContains('/link-social/twitter'); + $this->assertResponseContains(' Connect with Google'); + $this->assertResponseNotContains('Connected with Google'); + $this->assertResponseContains('Social Accounts'); + $this->assertResponseContains('
'); + $this->assertResponseContains(''); + $this->assertResponseNotContains(''); + $this->assertResponseNotContains('/link-social/amazon'); + $this->assertResponseNotContains(''); + + $this->get('/users/change-password'); + $this->assertResponseOk(); + + $this->enableSecurityToken(); + $this->post('/users/change-password', [ + 'password' => '98765432102', + 'password_confirm' => '98765432102' + ]); + $this->assertRedirect('/profile'); + $this->assertFlashMessage('Password has been changed successfully'); + } +} From c8e915264b3a4e3df85cbd576c01a1681e0d43dc Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 19:00:00 -0300 Subject: [PATCH 503/685] Integration test for crud actions --- .../SimpleCrudTraitIntegrationTest.php | 137 ++++++++++++++++++ tests/test_app/TestApp/Application.php | 3 +- 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php diff --git a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php new file mode 100644 index 000000000..e1e9cb645 --- /dev/null +++ b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php @@ -0,0 +1,137 @@ +get('CakeDC/Users.Users') + ->get($userId); + + $this->session(['Auth' => $user]); + $this->enableRetainFlashMessages(); + $this->get('/users/index'); + $this->assertResponseOk(); + $this->assertResponseContains('New Users'); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains('View'); + $this->assertResponseContains('Change password'); + $this->assertResponseContains('Edit'); + $this->assertResponseContains('style="display:none;" method="post" action="/users/delete/00000000-0000-0000-0000-000000000001"'); + $this->assertResponseContains('>Delete<'); + + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains('View'); + $this->assertResponseContains('Change password'); + $this->assertResponseContains('Edit'); + $this->assertResponseContains('style="display:none;" method="post" action="/users/delete/00000000-0000-0000-0000-000000000006"'); + + $this->get('/users/change-password/00000000-0000-0000-0000-000000000006'); + $this->assertFlashMessage('Changing another user\'s password is not allowed'); + $this->assertRedirect('/profile'); + + EventManager::instance()->on(Application::EVENT_AFTER_PLUGIN_BOOTSTRAP, function() { + Configure::write('Users.Superuser.allowedToChangePasswords', true); + }); + $this->get('/users/change-password/00000000-0000-0000-0000-000000000005'); + $this->assertResponseOk(); + $this->assertResponseContains(''); + $this->assertResponseContains('assertResponseContains('assertResponseContains(''); + + $this->enableSecurityToken(); + $this->post('/users/change-password/00000000-0000-0000-0000-000000000005', [ + 'password' => '123456', + 'password_confirm' => '123456' + ]); + $this->assertRedirect('/users/index'); + $this->assertFlashMessage('Password has been changed successfully'); + + $this->get("/users/edit/00000000-0000-0000-0000-000000000006"); + $this->assertResponseContains('assertResponseContains('assertResponseContains('Active'); + $this->assertResponseContains('style="display:none;" method="post" action="/users/delete/00000000-0000-0000-0000-000000000006"'); + $this->assertResponseContains('List Users'); + + $this->enableSecurityToken(); + $this->post("/users/edit/00000000-0000-0000-0000-000000000006", [ + 'username' => 'my-new-username', + 'email' => 'crud.email992@example.com', + 'first_name' => 'Joe', + 'last_name' => 'Doe K' + ]); + $this->assertRedirect('/users/index'); + $this->assertFlashMessage('The User has been saved'); + $this->get("/users/view/00000000-0000-0000-0000-000000000006"); + $this->assertResponseOk(); + $this->assertResponseContains('>00000000-0000-0000-0000-000000000006<'); + $this->assertResponseContains('>my-new-username<'); + $this->assertResponseContains('>crud.email992@example.com<'); + $this->assertResponseContains('>Joe<'); + $this->assertResponseContains('>Doe K<'); + $this->assertResponseContains('>token-6<'); + $this->assertResponseContains('Edit User'); + $this->assertResponseContains('New User'); + $this->assertResponseContains('List Users'); + $this->assertResponseContains('style="display:none;" method="post" action="/users/delete/00000000-0000-0000-0000-000000000006"'); + + $this->post('/users/delete/00000000-0000-0000-0000-000000000006'); + $this->assertRedirect('/users/index'); + $this->assertFlashMessage('The User has been deleted'); + + $this->get('/users/index'); + $this->assertResponseOk(); + $this->assertResponseNotContains('00000000-0000-0000-0000-000000000006'); + $this->assertResponseContains('00000000-0000-0000-0000-000000000001'); + } +} diff --git a/tests/test_app/TestApp/Application.php b/tests/test_app/TestApp/Application.php index 0184d175c..58ceee60c 100644 --- a/tests/test_app/TestApp/Application.php +++ b/tests/test_app/TestApp/Application.php @@ -21,6 +21,7 @@ class Application extends BaseApplication { + const EVENT_AFTER_PLUGIN_BOOTSTRAP = 'TestApp.afterPluginBootstrap'; /** * @inheritDoc @@ -39,7 +40,7 @@ public function pluginBootstrap(): void { Configure::write('Users.config', ['users']); parent::pluginBootstrap(); - $this->dispatchEvent('TestApp.afterPluginBootstrap'); + $this->dispatchEvent(static::EVENT_AFTER_PLUGIN_BOOTSTRAP); } /** From 4eb81bcce8c6cc51d3cd9e2628fa19499afb5147 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 19:36:08 -0300 Subject: [PATCH 504/685] phpcs fixes and avoid error with email transport --- .../Integration/LoginTraitIntegrationTest.php | 14 +++++++------- ...PasswordManagementTraitIntegrationTest.php | 7 +++---- .../ProfileTraitIntegrationTest.php | 4 +--- .../RegisterTraitIntegrationTest.php | 5 ++--- .../SimpleCrudTraitIntegrationTest.php | 6 +++--- tests/bootstrap.php | 2 -- tests/config/bootstrap.php | 12 ------------ tests/test_app/TestApp/Application.php | 19 +++++++++++++++++-- tests/test_app/config/routes.php | 12 ++++++++++-- tests/test_app/config/users.php | 2 +- 10 files changed, 44 insertions(+), 39 deletions(-) diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index 097558630..ff0a13731 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -65,7 +65,7 @@ public function testRedirectToLogin() */ public function testLoginGetRequestNoSocialLogin() { - EventManager::instance()->on('TestApp.afterPluginBootstrap', function() { + EventManager::instance()->on('TestApp.afterPluginBootstrap', function () { Configure::write(['Users.Social.login' => false]); }); @@ -123,7 +123,7 @@ public function testLoginPostRequestInvalidPassword() { $this->post('/login', [ 'username' => 'user-2', - 'password' => '123456789' + 'password' => '123456789', ]); $this->assertResponseOk(); $this->assertResponseContains('Username or password is incorrect'); @@ -145,7 +145,7 @@ public function testLoginPostRequestRightPassword() $this->enableRetainFlashMessages(); $this->post('/login', [ 'username' => 'user-2', - 'password' => '12345' + 'password' => '12345', ]); $this->assertRedirect('/pages/home'); } @@ -157,13 +157,13 @@ public function testLoginPostRequestRightPassword() */ public function testLoginPostRequestRightPasswordIsEnabledOTP() { - EventManager::instance()->on('TestApp.afterPluginBootstrap', function() { + EventManager::instance()->on('TestApp.afterPluginBootstrap', function () { Configure::write(['OneTimePasswordAuthenticator.login' => true]); }); $this->enableRetainFlashMessages(); $this->post('/login', [ 'username' => 'user-2', - 'password' => '12345' + 'password' => '12345', ]); $this->assertRedirect('/verify'); } @@ -175,13 +175,13 @@ public function testLoginPostRequestRightPasswordIsEnabledOTP() */ public function testLoginPostRequestRightPasswordIsEnabledU2f() { - EventManager::instance()->on('TestApp.afterPluginBootstrap', function() { + EventManager::instance()->on('TestApp.afterPluginBootstrap', function () { Configure::write(['U2f.enabled' => true]); }); $this->enableRetainFlashMessages(); $this->post('/login', [ 'username' => 'user-2', - 'password' => '12345' + 'password' => '12345', ]); $this->assertRedirect('/users/u2f'); } diff --git a/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php index d44d053cf..55e3b09e6 100644 --- a/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php @@ -14,7 +14,6 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits\Integration; use Cake\Core\Configure; -use Cake\Event\EventManager; use Cake\ORM\TableRegistry; use Cake\TestSuite\IntegrationTestTrait; use Cake\TestSuite\TestCase; @@ -71,9 +70,9 @@ public function testRequestResetPasswordPostValidEmail() $this->assertRedirect('/users/change-password'); $fieldName = Configure::read('Users.Key.Session.resetPasswordUserId'); - $this->assertSession($userAfter->id , $fieldName); + $this->assertSession($userAfter->id, $fieldName); $this->session([ - $fieldName => $userAfter->id + $fieldName => $userAfter->id, ]); $this->get('/users/change-password'); $this->assertResponseOk(); @@ -86,7 +85,7 @@ public function testRequestResetPasswordPostValidEmail() $this->post('/users/change-password', [ 'password' => '9080706050', - 'password_confirm' => '9080706050' + 'password_confirm' => '9080706050', ]); $this->assertRedirect('/login'); $this->assertFlashMessage('Password has been changed successfully'); diff --git a/tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php index 75e6403ba..8ee17b6dc 100644 --- a/tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php @@ -13,8 +13,6 @@ namespace CakeDC\Users\Test\TestCase\Controller\Traits\Integration; -use Cake\Core\Configure; -use Cake\Event\EventManager; use Cake\ORM\TableRegistry; use Cake\TestSuite\IntegrationTestTrait; use Cake\TestSuite\TestCase; @@ -72,7 +70,7 @@ public function testProfile() $this->enableSecurityToken(); $this->post('/users/change-password', [ 'password' => '98765432102', - 'password_confirm' => '98765432102' + 'password_confirm' => '98765432102', ]); $this->assertRedirect('/profile'); $this->assertFlashMessage('Password has been changed successfully'); diff --git a/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php index a4683d39e..0866a5c84 100644 --- a/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php @@ -30,7 +30,6 @@ class RegisterTraitIntegrationTest extends TestCase 'plugin.CakeDC/Users.Users', ]; - /** * Test register action * @@ -69,7 +68,7 @@ public function testRegisterPostWithErrors() 'password_confirm' => '11', 'first_name' => '', 'last_name' => '', - 'tos' => '0' + 'tos' => '0', ]; $this->post('/register', $data); $this->assertResponseOk(); @@ -106,7 +105,7 @@ public function testRegisterPostOkay() 'password_confirm' => '123456', 'first_name' => '', 'last_name' => '', - 'tos' => '0' + 'tos' => '0', ]; $this->post('/register', $data); $this->assertRedirect('/login'); diff --git a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php index e1e9cb645..5317cde74 100644 --- a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php @@ -74,7 +74,7 @@ public function testCrud() $this->assertFlashMessage('Changing another user\'s password is not allowed'); $this->assertRedirect('/profile'); - EventManager::instance()->on(Application::EVENT_AFTER_PLUGIN_BOOTSTRAP, function() { + EventManager::instance()->on(Application::EVENT_AFTER_PLUGIN_BOOTSTRAP, function () { Configure::write('Users.Superuser.allowedToChangePasswords', true); }); $this->get('/users/change-password/00000000-0000-0000-0000-000000000005'); @@ -87,7 +87,7 @@ public function testCrud() $this->enableSecurityToken(); $this->post('/users/change-password/00000000-0000-0000-0000-000000000005', [ 'password' => '123456', - 'password_confirm' => '123456' + 'password_confirm' => '123456', ]); $this->assertRedirect('/users/index'); $this->assertFlashMessage('Password has been changed successfully'); @@ -108,7 +108,7 @@ public function testCrud() 'username' => 'my-new-username', 'email' => 'crud.email992@example.com', 'first_name' => 'Joe', - 'last_name' => 'Doe K' + 'last_name' => 'Doe K', ]); $this->assertRedirect('/users/index'); $this->assertFlashMessage('The User has been saved'); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 4e16bdba3..a4d7b4530 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -19,7 +19,6 @@ * installed as a dependency of an application. */ -use Cake\Core\Configure; use Cake\Core\Plugin; $findRoot = function ($root) { @@ -100,7 +99,6 @@ require $root . '/config/bootstrap.php'; } - if (!getenv('db_dsn')) { putenv('db_dsn=sqlite:///:memory:'); } diff --git a/tests/config/bootstrap.php b/tests/config/bootstrap.php index a46ff25c2..02b4c265e 100644 --- a/tests/config/bootstrap.php +++ b/tests/config/bootstrap.php @@ -28,16 +28,4 @@ 'templates' => [dirname(APP) . DS . 'templates' . DS], ], ]); -\Cake\Mailer\TransportFactory::setConfig([ - 'default' => [ - 'className' => \Cake\Mailer\Transport\DebugTransport::class, - ], -]); -\Cake\Mailer\Email::setConfig([ - 'default' => [ - 'transport' => 'default', - 'from' => 'you@localhost', - ], -]); \Cake\Utility\Security::setSalt('yoyz186elmi66ab9pz4imbb3tgy9vnsgsfgwe2r8tyxbbfdygu9e09tlxyg8p7dq'); - diff --git a/tests/test_app/TestApp/Application.php b/tests/test_app/TestApp/Application.php index 58ceee60c..f34718450 100644 --- a/tests/test_app/TestApp/Application.php +++ b/tests/test_app/TestApp/Application.php @@ -1,5 +1,6 @@ [ + 'className' => \Cake\Mailer\Transport\DebugTransport::class, + ], + ]); + } + if (!\Cake\Mailer\Email::getConfig('default')) { + \Cake\Mailer\Email::setConfig([ + 'default' => [ + 'transport' => 'default', + 'from' => 'you@localhost', + ], + ]); + } $this->addPlugin(Plugin::class); } diff --git a/tests/test_app/config/routes.php b/tests/test_app/config/routes.php index 06073b99f..9b3ff54d8 100644 --- a/tests/test_app/config/routes.php +++ b/tests/test_app/config/routes.php @@ -1,7 +1,15 @@ setRouteClass(DashedRoute::class); diff --git a/tests/test_app/config/users.php b/tests/test_app/config/users.php index 77ecdc76a..35e35adcd 100644 --- a/tests/test_app/config/users.php +++ b/tests/test_app/config/users.php @@ -8,5 +8,5 @@ 'OAuth.providers.twitter.options.clientId' => 'QWERTY0009', 'OAuth.providers.twitter.options.clientSecret' => '999988899', 'OAuth.providers.google.options.clientId' => '0000000990909090', - 'OAuth.providers.google.options.clientSecret'=> '1565464559789798', + 'OAuth.providers.google.options.clientSecret' => '1565464559789798', ]; From c10d2a9c890de08286e0ff3df5fd9dfdfa849933 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 19:50:05 -0300 Subject: [PATCH 505/685] Using same phpstan version as cakephp/cakephp --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3226dfc7f..96e3b0b23 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ "test": "phpunit --stderr", "stan": "phpstan analyse src/", "psalm": "php vendor/psalm/phar/psalm.phar --show-info=false src/ ", - "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12 psalm/phar:^3.5 && mv composer.backup composer.json", + "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12.7 psalm/phar:~3.8.0 && mv composer.backup composer.json", "stan-rebuild-baseline": "phpstan analyse --configuration phpstan.neon --error-format baselineNeon src/ > phpstan-baseline.neon", "psalm-rebuild-baseline": "php vendor/psalm/phar/psalm.phar --show-info=false --set-baseline=psalm-baseline.xml src/", "rector": "rector process src/", From 34a2b67f5119aa0ad0c50b9670854bc0fa3b647f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 19:50:21 -0300 Subject: [PATCH 506/685] Removed unused files --- .../text/custom_template_in_app_namespace.php | 6 ------ tests/templates/layout/Email/html/default.php | 14 -------------- tests/templates/layout/Email/text/default.php | 14 -------------- 3 files changed, 34 deletions(-) delete mode 100644 tests/templates/Email/text/custom_template_in_app_namespace.php delete mode 100644 tests/templates/layout/Email/html/default.php delete mode 100644 tests/templates/layout/Email/text/default.php diff --git a/tests/templates/Email/text/custom_template_in_app_namespace.php b/tests/templates/Email/text/custom_template_in_app_namespace.php deleted file mode 100644 index 59a6fcf3d..000000000 --- a/tests/templates/Email/text/custom_template_in_app_namespace.php +++ /dev/null @@ -1,6 +0,0 @@ - -some custom template here diff --git a/tests/templates/layout/Email/html/default.php b/tests/templates/layout/Email/html/default.php deleted file mode 100644 index 178fe0aaa..000000000 --- a/tests/templates/layout/Email/html/default.php +++ /dev/null @@ -1,14 +0,0 @@ -fetch('content'); diff --git a/tests/templates/layout/Email/text/default.php b/tests/templates/layout/Email/text/default.php deleted file mode 100644 index 178fe0aaa..000000000 --- a/tests/templates/layout/Email/text/default.php +++ /dev/null @@ -1,14 +0,0 @@ -fetch('content'); From a5b1af8fd13f2c42879baca1ee1df74d3ebfb343 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 19:54:57 -0300 Subject: [PATCH 507/685] Moving test class to test_app/TestApp --- tests/TestCase/Model/Behavior/PasswordBehaviorTest.php | 2 +- tests/{App => test_app/TestApp}/Mailer/OverrideMailer.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/{App => test_app/TestApp}/Mailer/OverrideMailer.php (96%) diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index e41f3c403..84c275907 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -23,7 +23,7 @@ use CakeDC\Users\Exception\UserNotFoundException; use CakeDC\Users\Model\Behavior\PasswordBehavior; use CakeDC\Users\Model\Entity\User; -use CakeDC\Users\Test\App\Mailer\OverrideMailer; +use TestApp\Mailer\OverrideMailer; /** * Test Case diff --git a/tests/App/Mailer/OverrideMailer.php b/tests/test_app/TestApp/Mailer/OverrideMailer.php similarity index 96% rename from tests/App/Mailer/OverrideMailer.php rename to tests/test_app/TestApp/Mailer/OverrideMailer.php index 5e1fa2d4b..792001a4f 100644 --- a/tests/App/Mailer/OverrideMailer.php +++ b/tests/test_app/TestApp/Mailer/OverrideMailer.php @@ -11,7 +11,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Test\App\Mailer; +namespace TestApp\Mailer; use Cake\Datasource\EntityInterface; use CakeDC\Users\Mailer\UsersMailer; From 672b48599a2b46bc37009f25b382e9c687e4a10f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 19:57:38 -0300 Subject: [PATCH 508/685] Moving test class to test_app/TestApp --- tests/TestCase/Middleware/SocialAuthMiddlewareTest.php | 2 +- tests/{App => test_app/TestApp}/Http/TestRequestHandler.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/{App => test_app/TestApp}/Http/TestRequestHandler.php (94%) diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index dfc18261e..de714d186 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -25,9 +25,9 @@ use CakeDC\Users\Exception\MissingEmailException; use CakeDC\Users\Exception\SocialAuthenticationException; use CakeDC\Users\Middleware\SocialAuthMiddleware; -use CakeDC\Users\Test\App\Http\TestRequestHandler; use Doctrine\Instantiator\Exception\UnexpectedValueException; use League\OAuth2\Client\Provider\FacebookUser; +use TestApp\Http\TestRequestHandler; use Zend\Diactoros\Uri; class SocialAuthMiddlewareTest extends TestCase diff --git a/tests/App/Http/TestRequestHandler.php b/tests/test_app/TestApp/Http/TestRequestHandler.php similarity index 94% rename from tests/App/Http/TestRequestHandler.php rename to tests/test_app/TestApp/Http/TestRequestHandler.php index 783a388b0..fe913db9b 100644 --- a/tests/App/Http/TestRequestHandler.php +++ b/tests/test_app/TestApp/Http/TestRequestHandler.php @@ -1,7 +1,7 @@ Date: Fri, 31 Jan 2020 19:59:32 -0300 Subject: [PATCH 509/685] Moving test class to test_app/TestApp --- tests/bootstrap.php | 2 +- tests/{App => test_app/TestApp}/Controller/AppController.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/{App => test_app/TestApp}/Controller/AppController.php (95%) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index a4d7b4530..b725c6748 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -108,7 +108,7 @@ 'timezone' => 'UTC', ]); -class_alias('CakeDC\Users\Test\App\Controller\AppController', 'App\Controller\AppController'); +class_alias('TestApp\Controller\AppController', 'App\Controller\AppController'); $app = new \CakeDC\Users\Test\TestApplication(__DIR__ . DS . 'config'); $app->bootstrap(); diff --git a/tests/App/Controller/AppController.php b/tests/test_app/TestApp/Controller/AppController.php similarity index 95% rename from tests/App/Controller/AppController.php rename to tests/test_app/TestApp/Controller/AppController.php index 5b4e612c2..947d6a0c4 100644 --- a/tests/App/Controller/AppController.php +++ b/tests/test_app/TestApp/Controller/AppController.php @@ -11,7 +11,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -namespace CakeDC\Users\Test\App\Controller; +namespace TestApp\Controller; use Cake\Controller\Controller; From 22565194abe9ff3e5982a35b8664a2d39b538e81 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 20:20:52 -0300 Subject: [PATCH 510/685] Removed unnecessary files --- tests/TestApplication.php | 60 -------------------------------------- tests/bootstrap.php | 23 +++++++++++++-- tests/config/bootstrap.php | 31 -------------------- tests/config/routes.php | 35 ---------------------- 4 files changed, 20 insertions(+), 129 deletions(-) delete mode 100644 tests/TestApplication.php delete mode 100644 tests/config/bootstrap.php delete mode 100644 tests/config/routes.php diff --git a/tests/TestApplication.php b/tests/TestApplication.php deleted file mode 100644 index 3e925c15f..000000000 --- a/tests/TestApplication.php +++ /dev/null @@ -1,60 +0,0 @@ -add(ErrorHandlerMiddleware::class) - ->add(AssetMiddleware::class) - ->add(new RoutingMiddleware($this, null)); - - return $middlewareQueue; - } - - /** - * {@inheritDoc} - */ - public function bootstrap(): void - { - parent::bootstrap(); - $this->addPlugin('CakeDC/Users', [ - 'path' => dirname(dirname(__FILE__)) . DS, - 'routes' => true, - ]); - } -} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index b725c6748..e8575c540 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -110,7 +110,24 @@ class_alias('TestApp\Controller\AppController', 'App\Controller\AppController'); -$app = new \CakeDC\Users\Test\TestApplication(__DIR__ . DS . 'config'); -$app->bootstrap(); -$app->pluginBootstrap(); +\Cake\Core\Configure::write('App', [ + 'namespace' => 'TestApp', + 'encoding' => 'UTF-8', + 'base' => false, + 'baseUrl' => false, + 'dir' => 'src', + 'webroot' => WEBROOT_DIR, + 'wwwRoot' => WWW_ROOT, + 'fullBaseUrl' => 'http://localhost', + 'imageBaseUrl' => 'img/', + 'jsBaseUrl' => 'js/', + 'cssBaseUrl' => 'css/', + 'paths' => [ + 'plugins' => [dirname(APP) . DS . 'plugins' . DS], + 'templates' => [dirname(APP) . DS . 'templates' . DS], + ], +]); +\Cake\Utility\Security::setSalt('yoyz186elmi66ab9pz4imbb3tgy9vnsgsfgwe2r8tyxbbfdygu9e09tlxyg8p7dq'); + +Plugin::getCollection()->add(new \CakeDC\Users\Plugin()); session_id('cli'); diff --git a/tests/config/bootstrap.php b/tests/config/bootstrap.php deleted file mode 100644 index 02b4c265e..000000000 --- a/tests/config/bootstrap.php +++ /dev/null @@ -1,31 +0,0 @@ - 'TestApp', - 'encoding' => 'UTF-8', - 'base' => false, - 'baseUrl' => false, - 'dir' => 'src', - 'webroot' => WEBROOT_DIR, - 'wwwRoot' => WWW_ROOT, - 'fullBaseUrl' => 'http://localhost', - 'imageBaseUrl' => 'img/', - 'jsBaseUrl' => 'js/', - 'cssBaseUrl' => 'css/', - 'paths' => [ - 'plugins' => [dirname(APP) . DS . 'plugins' . DS], - 'templates' => [dirname(APP) . DS . 'templates' . DS], - ], -]); -\Cake\Utility\Security::setSalt('yoyz186elmi66ab9pz4imbb3tgy9vnsgsfgwe2r8tyxbbfdygu9e09tlxyg8p7dq'); diff --git a/tests/config/routes.php b/tests/config/routes.php deleted file mode 100644 index 8043411b4..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']); From 0308c71418b986024ae9b42d9f0176f53b396565 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 31 Jan 2020 20:30:35 -0300 Subject: [PATCH 511/685] avoid warns in unit test --- .../TestCase/Controller/SocialAccountsControllerTest.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Controller/SocialAccountsControllerTest.php b/tests/TestCase/Controller/SocialAccountsControllerTest.php index 4f4792297..47a544d7e 100644 --- a/tests/TestCase/Controller/SocialAccountsControllerTest.php +++ b/tests/TestCase/Controller/SocialAccountsControllerTest.php @@ -57,12 +57,9 @@ public function setUp(): void $request = $request->withParam('plugin', 'CakeDC/Users'); $this->Controller = $this->getMockBuilder('CakeDC\Users\Controller\SocialAccountsController') - ->setMethods(['redirect', 'render']) + ->onlyMethods(['redirect', 'render']) ->setConstructorArgs([$request, null, 'SocialAccounts']) ->getMock(); - $this->Controller->SocialAccounts = $this->getMockForModel('CakeDC\Users.SocialAccounts', ['sendSocialValidationEmail'], [ - 'className' => 'CakeDC\Users\Model\Table\SocialAccountsTable', - ]); } /** @@ -132,7 +129,7 @@ public function testValidateAccountAlreadyActive() public function testResendValidationHappy() { $behaviorMock = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialAccountBehavior') - ->setMethods(['sendSocialValidationEmail']) + ->onlyMethods(['sendSocialValidationEmail']) ->setConstructorArgs([$this->Controller->SocialAccounts]) ->getMock(); $this->Controller->SocialAccounts->behaviors()->set('SocialAccount', $behaviorMock); @@ -155,7 +152,7 @@ public function testResendValidationHappy() public function testResendValidationEmailError() { $behaviorMock = $this->getMockBuilder('CakeDC\Users\Model\Behavior\SocialAccountBehavior') - ->setMethods(['sendSocialValidationEmail']) + ->onlyMethods(['sendSocialValidationEmail']) ->setConstructorArgs([$this->Controller->SocialAccounts]) ->getMock(); $this->Controller->SocialAccounts->behaviors()->set('SocialAccount', $behaviorMock); From b85776fcdec73a169a3caa11b75b03098718e47b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 3 Feb 2020 13:37:07 -0300 Subject: [PATCH 512/685] 9.0 release --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index de7361321..5b534a03e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ Changelog ========= +Releases for CakePHP 4 +------------- +* 9.0.0 + * Migration to CakePHP 4 + * Compatible with cakephp/authentication + * Compatible with cakephp/authorization + * Added/removed/changed some configurations to work with new authentication/authorization plugins, please check Migration guide for more info. + * Events constants were moved/removed from AuthComponent to Plugin class and their values was also updated, please check Migration guide for more info. + * Migrated usage of AuthComponent to Authorization/Authentication plugins. Releases for CakePHP 3 ------------- From 29f2a08fbb9b7c1643c315dded544b136cdddcd7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 3 Feb 2020 13:43:37 -0300 Subject: [PATCH 513/685] Release 9.0.1 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b534a03e..ca0a0ede9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ Changelog ========= Releases for CakePHP 4 ------------- +* 9.0.1 + * Improved routes + * Improved integration tests + * Fixed warnings related to arguments in function calls + * 9.0.0 * Migration to CakePHP 4 * Compatible with cakephp/authentication From ca23913a9a9ae7f061aefc20c38c10ecccb3312a Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 3 Feb 2020 13:48:01 -0300 Subject: [PATCH 514/685] Update CHANGELOG.md --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca0a0ede9..08d4d0a3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,8 @@ Releases for CakePHP 4 * Migration to CakePHP 4 * Compatible with cakephp/authentication * Compatible with cakephp/authorization - * Added/removed/changed some configurations to work with new authentication/authorization plugins, please check Migration guide for more info. - * Events constants were moved/removed from AuthComponent to Plugin class and their values was also updated, please check Migration guide for more info. + * Added/removed/changed some configurations to work with new authentication/authorization plugins, [please check Migration guide for more info](https://github.com/CakeDC/users/blob/9.next/Docs/Documentation/Migration/8.x-9.0.md). + * Events constants were moved/removed from AuthComponent to Plugin class and their values was also updated, [please check Migration guide for more info](https://github.com/CakeDC/users/blob/9.next/Docs/Documentation/Migration/8.x-9.0.md). * Migrated usage of AuthComponent to Authorization/Authentication plugins. Releases for CakePHP 3 From cabe6328468b1872302b66e85a050ef0b559509b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 4 Feb 2020 08:14:32 -0300 Subject: [PATCH 515/685] Release 9.0.1 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 33d0038c6..d52e3e178 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| 3.7 | [master](https://github.com/cakedc/users/tree/master) | 8.5.1 | stable | +| ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.1 | stable | | 3.7 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | -| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.0 | stable | +| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.1 | stable | | ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | | 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | | 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | From d8988fc14ed5eb1471a09c684187e3e7bb9bfacb Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 4 Feb 2020 08:16:03 -0300 Subject: [PATCH 516/685] Release 9.0.1 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d52e3e178..130149aa8 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | | ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.1 | stable | -| 3.7 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.1 | stable | | ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | +| 3.7 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | | 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | | 3.4 | [5.x](https://github.com/cakedc/users/tree/5.x) | 5.2.0 | stable | From f2b0ae766fdcb715290afa9fc7b4aaab79f94b2a Mon Sep 17 00:00:00 2001 From: Maxime Date: Wed, 5 Feb 2020 15:02:33 +0100 Subject: [PATCH 517/685] Fix error on test logged as Admin with Mock method --- .../View/Helper/AuthLinkHelperTest.php | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php index e134028a5..15c6d970d 100644 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -153,20 +153,20 @@ public function testPostLinkAuthorizedAllowedTrueLoggedAsAdmin() 'action' => 'delete', '00000000-0000-0000-0000-000000000010', ]; - - $this->AuthLink->expects($this->any()) - ->method('allowMethod') - ->with(['post', 'delete']) + Router::connect('/profile', $url); + $this->AuthLink->expects($this->once()) + ->method('isAuthorized') + ->with( + $this->equalTo($url) + ) ->will($this->returnValue(true)); - $link = $this->AuthLink->postLink('Post Link Title', $url, [ - 'allowed' => true, - 'class' => 'link-class', - 'confirm' => 'confirmation message', - ]); - - $this->assertContains('confirmation message', $link); - $this->assertContains('Post Link Title', $link); + 'allowed' => true, + 'class' => 'link-class', + 'confirm' => 'confirmation message', + ]); + $this->assertStringContainsString('data-confirm-message="confirmation message"', $link); + $this->assertStringContainsString('Post Link Title', $link); } /** From 74d9c7420b4bc84b9e57baa4878e8d2e7162d02f Mon Sep 17 00:00:00 2001 From: Maxime Date: Wed, 5 Feb 2020 15:09:48 +0100 Subject: [PATCH 518/685] Remove prefix on route connect --- tests/TestCase/View/Helper/AuthLinkHelperTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php index 15c6d970d..2acb5a8ca 100644 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -147,13 +147,12 @@ public function testGetRequest() public function testPostLinkAuthorizedAllowedTrueLoggedAsAdmin() { $url = [ - 'prefix' => false, 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'delete', '00000000-0000-0000-0000-000000000010', ]; - Router::connect('/profile', $url); + Router::connect('/Users/delete/00000000-0000-0000-0000-000000000010', $url); $this->AuthLink->expects($this->once()) ->method('isAuthorized') ->with( From fe0eaf75b183fab0891d3f38ca38b3d1fad1ad9b Mon Sep 17 00:00:00 2001 From: Maxime Date: Wed, 5 Feb 2020 15:42:29 +0100 Subject: [PATCH 519/685] add typehint on methods --- src/View/Helper/AuthLinkHelper.php | 8 ++++---- .../View/Helper/AuthLinkHelperTest.php | 20 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index bc4fd6f86..ab4af59ac 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -58,15 +58,15 @@ public function link($title, $url = null, array $options = []): string * Write the link only if user is authorized. * * @param string $title Link's title - * @param [type] $url Link's url + * @param string|array $url Link's url * @param array $options Link's options - * @return string|bool Link as a string or false. + * @return string Link as a string. */ - public function postLink($title, $url = null, array $options = []) + public function postLink($title, $url = null, array $options = []): string { return $this->isAuthorized($url) ? $this->Form->postLink($title, $url, $options) - : false; + : ''; } /** diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php index 2acb5a8ca..cae56eacb 100644 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -63,7 +63,7 @@ public function tearDown(): void * * @return void */ - public function testLinkFalseWithMock() + public function testLinkFalseWithMock(): void { $this->AuthLink->expects($this->once()) ->method('isAuthorized') @@ -84,7 +84,7 @@ public function testLinkFalseWithMock() * * @return void */ - public function testLinkAuthorizedHappy() + public function testLinkAuthorizedHappy(): void { Router::connect('/profile', [ 'plugin' => 'CakeDC/Users', @@ -110,7 +110,7 @@ public function testLinkAuthorizedHappy() * * @return void */ - public function testLinkAuthorizedAllowedTrue() + public function testLinkAuthorizedAllowedTrue(): void { $link = $this->AuthLink->link('title', '/', ['allowed' => true, 'before' => 'before_', 'after' => '_after', 'class' => 'link-class']); $this->assertSame('before_title_after', $link); @@ -121,7 +121,7 @@ public function testLinkAuthorizedAllowedTrue() * * @return void */ - public function testLinkAuthorizedAllowedFalse() + public function testLinkAuthorizedAllowedFalse(): void { $link = $this->AuthLink->link('title', '/', ['allowed' => false, 'before' => 'before_', 'after' => '_after', 'class' => 'link-class']); $this->assertEmpty($link); @@ -132,7 +132,7 @@ public function testLinkAuthorizedAllowedFalse() * * @retunr void */ - public function testGetRequest() + public function testGetRequest(): void { $actual = $this->AuthLink->getRequest(); $this->assertInstanceOf(ServerRequest::class, $actual); @@ -144,7 +144,7 @@ public function testGetRequest() * * @return void */ - public function testPostLinkAuthorizedAllowedTrueLoggedAsAdmin() + public function testPostLinkAuthorizedAllowedTrueLoggedAsAdmin(): void { $url = [ 'plugin' => 'CakeDC/Users', @@ -174,7 +174,7 @@ public function testPostLinkAuthorizedAllowedTrueLoggedAsAdmin() * * @return void */ - public function testPostLinkAuthorizedAllowedFalseLoggedWithoutRole() + public function testPostLinkAuthorizedAllowedFalseLoggedWithoutRole(): void { $url = [ 'prefix' => false, @@ -197,7 +197,7 @@ public function testPostLinkAuthorizedAllowedFalseLoggedWithoutRole() 'confirm' => 'confirmation message', ]); - $this->assertFalse($link); + $this->assertEmpty($link); } /** @@ -205,7 +205,7 @@ public function testPostLinkAuthorizedAllowedFalseLoggedWithoutRole() * * @return void */ - public function testPostLinkAuthorizedAllowedFalse() + public function testPostLinkAuthorizedAllowedFalse(): void { $url = [ 'prefix' => false, @@ -227,6 +227,6 @@ public function testPostLinkAuthorizedAllowedFalse() 'class' => 'link-class', 'confirm' => 'confirmation message', ]); - $this->assertFalse($link); + $this->assertEmpty($link); } } From ed009e96b35ff0f9934d8672297a50f33e371a1e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 13 Feb 2020 15:51:14 -0300 Subject: [PATCH 520/685] Added a customized default handler for unauthorized access --- config/users.php | 2 +- .../DefaultRedirectHandler.php | 65 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php diff --git a/config/users.php b/config/users.php index a5192f8a8..40e47cf78 100644 --- a/config/users.php +++ b/config/users.php @@ -199,7 +199,7 @@ 'MissingIdentityException' => 'Authorization\Exception\MissingIdentityException', 'ForbiddenException' => 'Authorization\Exception\ForbiddenException', ], - 'className' => 'Authorization.CakeRedirect', + 'className' => 'CakeDC/Users.DefaultRedirect', ] ], 'AuthorizationComponent' => [ diff --git a/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php new file mode 100644 index 000000000..896ac6e8a --- /dev/null +++ b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php @@ -0,0 +1,65 @@ + [ + 'MissingIdentityException' => MissingIdentityException::class, + 'ForbiddenException' => ForbiddenException::class, + ], + 'url' => [ + 'controller' => 'Users', + 'action' => 'login', + ], + 'queryParam' => 'redirect', + 'statusCode' => 302, + ]; + + /** + * @inheritDoc + */ + protected function getUrl(ServerRequestInterface $request, array $options): string + { + $url = $options['url']; + if (is_callable($url)) { + return $url($request, $options); + } + + if ($request->getAttribute('identity')) { + return $request->referer() ?? '/'; + } + + if ($options['queryParam'] !== null) { + $url['?'][$options['queryParam']] = (string)$request->getUri(); + } + + return Router::url($url); + } +} From c1c27ab995ca49b73abd847863bef331b6676d10 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 13 Feb 2020 15:52:18 -0300 Subject: [PATCH 521/685] Added a customized default handler for unauthorized access --- .../Controller/UsersControllerTest.php | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 tests/TestCase/Controller/UsersControllerTest.php diff --git a/tests/TestCase/Controller/UsersControllerTest.php b/tests/TestCase/Controller/UsersControllerTest.php new file mode 100644 index 000000000..b7b311486 --- /dev/null +++ b/tests/TestCase/Controller/UsersControllerTest.php @@ -0,0 +1,94 @@ +assertInstanceOf(ServerRequest::class, $request); + $this->assertIsArray($options); + + return '/my/custom/url/'; + }); + $this->configRequest([ + 'headers' => [ + 'REFERER' => 'http://localhost/profile' + ] + ]); + $this->get('/users/index'); + $this->assertRedirect('/my/custom/url/'); + } + + /** + * Test unathorize redirect when user is NOT logged + * + * @return void + */ + public function testUnauthorizedRedirectNotLogged() + { + $this->configRequest([ + 'headers' => [ + 'REFERER' => 'http://localhost/profile' + ] + ]); + $this->get('/users/index'); + $this->assertRedirect('/login?redirect=http%3A%2F%2Flocalhost%2Fusers%2Findex'); + } + + /** + * Test unathorize redirect when user is logged + * + * @return void + */ + public function testUnauthorizedRedirectLogged() + { + $userId = '00000000-0000-0000-0000-000000000004'; + $user = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users') + ->get($userId); + + $this->session(['Auth' => $user]); + $this->configRequest([ + 'headers' => [ + 'REFERER' => 'http://localhost/profile' + ] + ]); + $this->get('/users/index'); + $this->assertRedirect('/profile'); + } +} From e14bb4c4a7bcfd7e8cf9797f8126add84463536c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 13 Feb 2020 15:53:29 -0300 Subject: [PATCH 522/685] On login check if user can access the redirect url from querystring --- src/Controller/Component/LoginComponent.php | 16 +++++++++- tests/Fixture/UsersFixture.php | 2 +- .../Integration/LoginTraitIntegrationTest.php | 32 ++++++++++++++++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index eefbb97d2..5db67b8d0 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -16,7 +16,9 @@ use Authentication\Authenticator\ResultInterface; use Cake\Controller\Component; use Cake\Core\Configure; +use Cake\Http\ServerRequest; use CakeDC\Auth\Authentication\AuthenticationService; +use CakeDC\Auth\Traits\IsAuthorizedTrait; use CakeDC\Users\Plugin; use CakeDC\Users\Utility\UsersUrl; @@ -25,6 +27,8 @@ */ class LoginComponent extends Component { + use IsAuthorizedTrait; + /** * Default configuration. * @@ -36,6 +40,16 @@ class LoginComponent extends Component 'targetAuthenticator' => null, ]; + /** + * Gets the request instance. + * + * @return \Cake\Http\ServerRequest + */ + public function getRequest(): ServerRequest + { + return $this->getController()->getRequest(); + } + /** * Handle login, if success redirect to 'AuthenticationComponent.loginRedirect' or show error * @@ -138,7 +152,7 @@ protected function afterIdentifyUser($user) $query = $this->getController()->getRequest()->getQueryParams(); $redirectUrl = $this->getController()->Authentication->getConfig('loginRedirect'); - if (isset($query['redirect'])) { + if ($this->isAuthorized($query['redirect'] ?? null)) { $redirectUrl = $query['redirect']; } diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index a16f1f936..b7bb8e61f 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -137,7 +137,7 @@ public function init(): void 'id' => '00000000-0000-0000-0000-000000000004', 'username' => 'user-4', 'email' => '4@example.com', - 'password' => 'Lorem ipsum dolor sit amet', + 'password' => '$2y$10$Nvu7ipP.z8tiIl75OdUvt.86vuG6iKMoHIOc7O7mboFI85hSyTEde', 'first_name' => 'FirstName4', 'last_name' => 'Lorem ipsum dolor sit amet', 'token' => 'token-4', diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index ff0a13731..4fe25fb29 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -140,7 +140,22 @@ public function testLoginPostRequestInvalidPassword() * * @return void */ - public function testLoginPostRequestRightPassword() + public function testLoginPostRequestRightPasswordWithBaseRedirectUrl() + { + $this->enableRetainFlashMessages(); + $this->post('/login?redirect=http://localhost/articles', [ + 'username' => 'user-2', + 'password' => '12345', + ]); + $this->assertRedirect('http://localhost/articles'); + } + + /** + * Test login action with post request + * + * @return void + */ + public function testLoginPostRequestRightPasswordNoBaseRedirectUrl() { $this->enableRetainFlashMessages(); $this->post('/login', [ @@ -150,6 +165,21 @@ public function testLoginPostRequestRightPassword() $this->assertRedirect('/pages/home'); } + /** + * Test login action with post request + * + * @return void + */ + public function testLoginPostRequestRightPasswordWithBaseRedirectUrlButCantAccess() + { + $this->enableRetainFlashMessages(); + $this->post('/login?redirect=http://localhost/articles', [ + 'username' => 'user-4', + 'password' => '12345', + ]); + $this->assertRedirect('/pages/home'); + } + /** * Test login action with post request * From eac17fd9e727310a170a70927509e7f028c04c0f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 13 Feb 2020 15:56:47 -0300 Subject: [PATCH 523/685] phpcs fixes --- tests/TestCase/Controller/UsersControllerTest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/TestCase/Controller/UsersControllerTest.php b/tests/TestCase/Controller/UsersControllerTest.php index b7b311486..a1f2505a5 100644 --- a/tests/TestCase/Controller/UsersControllerTest.php +++ b/tests/TestCase/Controller/UsersControllerTest.php @@ -39,7 +39,7 @@ class UsersControllerTest extends TestCase */ public function testUnauthorizedRedirectCustomCallable() { - Configure::write('Auth.AuthorizationMiddleware.unauthorizedHandler.url', function($request, $options) { + Configure::write('Auth.AuthorizationMiddleware.unauthorizedHandler.url', function ($request, $options) { $this->assertInstanceOf(ServerRequest::class, $request); $this->assertIsArray($options); @@ -47,8 +47,8 @@ public function testUnauthorizedRedirectCustomCallable() }); $this->configRequest([ 'headers' => [ - 'REFERER' => 'http://localhost/profile' - ] + 'REFERER' => 'http://localhost/profile', + ], ]); $this->get('/users/index'); $this->assertRedirect('/my/custom/url/'); @@ -63,8 +63,8 @@ public function testUnauthorizedRedirectNotLogged() { $this->configRequest([ 'headers' => [ - 'REFERER' => 'http://localhost/profile' - ] + 'REFERER' => 'http://localhost/profile', + ], ]); $this->get('/users/index'); $this->assertRedirect('/login?redirect=http%3A%2F%2Flocalhost%2Fusers%2Findex'); @@ -85,8 +85,8 @@ public function testUnauthorizedRedirectLogged() $this->session(['Auth' => $user]); $this->configRequest([ 'headers' => [ - 'REFERER' => 'http://localhost/profile' - ] + 'REFERER' => 'http://localhost/profile', + ], ]); $this->get('/users/index'); $this->assertRedirect('/profile'); From 479b4f1b9de8add0976b47c4f4d5dec825ffa662 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 13 Feb 2020 15:56:57 -0300 Subject: [PATCH 524/685] phpcs fixes --- tests/TestCase/Model/Behavior/PasswordBehaviorTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 84c275907..97268841b 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -15,6 +15,7 @@ use Cake\Core\Configure; use Cake\Mailer\Email; +use Cake\Mailer\Mailer; use Cake\Mailer\TransportFactory; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; @@ -56,7 +57,8 @@ public function setUp(): void TransportFactory::drop('test'); TransportFactory::setConfig('test', ['className' => 'Debug']); //$this->configEmail = Email::getConfig('default'); - Email::setConfig('default', [ + Mailer::drop('default'); + Mailer::setConfig('default', [ 'transport' => 'test', 'from' => 'cakedc@example.com', ]); From 95604498250480e286273f34ef54793e140125a6 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 13 Feb 2020 16:09:16 -0300 Subject: [PATCH 525/685] phpcs fixes --- src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php index 896ac6e8a..a0a4cd41a 100644 --- a/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php +++ b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php @@ -16,6 +16,7 @@ use Authorization\Exception\ForbiddenException; use Authorization\Exception\MissingIdentityException; use Authorization\Middleware\UnauthorizedHandler\CakeRedirectHandler; +use Cake\Http\ServerRequest; use Cake\Routing\Router; use Psr\Http\Message\ServerRequestInterface; @@ -52,7 +53,7 @@ protected function getUrl(ServerRequestInterface $request, array $options): stri return $url($request, $options); } - if ($request->getAttribute('identity')) { + if ($request->getAttribute('identity') && $request instanceof ServerRequest) { return $request->referer() ?? '/'; } From fe4c59b735e0448ac4dfecf1c4f7f1c99ca93255 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 13 Feb 2020 16:17:55 -0300 Subject: [PATCH 526/685] updated doc and default config --- Docs/Documentation/Authorization.md | 20 ++++++++----------- config/users.php | 4 ---- .../DefaultRedirectHandler.php | 1 + 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md index 9a6f01771..1afabb3e7 100644 --- a/Docs/Documentation/Authorization.md +++ b/Docs/Documentation/Authorization.md @@ -24,16 +24,12 @@ The default configuration for authorization middleware is: ``` [ 'unauthorizedHandler' => [ - 'exceptions' => [ - 'MissingIdentityException' => 'Authorization\Exception\MissingIdentityException', - 'ForbiddenException' => 'Authorization\Exception\ForbiddenException', - ], - 'className' => 'Authorization.CakeRedirect', + 'className' => 'CakeDC/Users.DefaultRedirect', ] ], ``` -You can check the configuration options available for authorization middleware at the +You can check the configuration options available for authorization middleware at the [official documentation](https://github.com/cakephp/authorization/blob/master/docs/Middleware.md) @@ -43,17 +39,17 @@ We autoload the authorization component at users controller using the default co if you don't want the plugin to autoload it, you can do: ``` Configure::write('Auth.AuthorizationComponent.enabled', false); -``` +``` -You can check the configuration options available for authorization component at the +You can check the configuration options available for authorization component at the [official documentation](https://github.com/cakephp/authorization/blob/master/docs/Component.md) -Authorization Service Loader +Authorization Service Loader ----------------------------- To make the integration with cakephp/authorization easier we load the resolvers OrmResolver and MapResolver. The MapResolver resolves ServerRequest request object to check access permission using Superuser and Rbac policies. -If the configuration is not enough for your project you may create a custom loader extending the +If the configuration is not enough for your project you may create a custom loader extending the default provided. - Create file src/Loader/AppAuthorizationServiceLoader.php @@ -61,9 +57,9 @@ default provided. ``` [ 'unauthorizedHandler' => [ - 'exceptions' => [ - 'MissingIdentityException' => 'Authorization\Exception\MissingIdentityException', - 'ForbiddenException' => 'Authorization\Exception\ForbiddenException', - ], 'className' => 'CakeDC/Users.DefaultRedirect', ] ], diff --git a/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php index a0a4cd41a..99f3331c7 100644 --- a/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php +++ b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php @@ -36,6 +36,7 @@ class DefaultRedirectHandler extends CakeRedirectHandler 'ForbiddenException' => ForbiddenException::class, ], 'url' => [ + 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', ], From a432b9b2a9b226d1a2268428876f2c86c4a396c7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 13 Feb 2020 16:29:19 -0300 Subject: [PATCH 527/685] Doc unauthorizedHandler url --- Docs/Documentation/Authorization.md | 30 ++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md index 1afabb3e7..9869983a3 100644 --- a/Docs/Documentation/Authorization.md +++ b/Docs/Documentation/Authorization.md @@ -30,9 +30,37 @@ The default configuration for authorization middleware is: ``` You can check the configuration options available for authorization middleware at the -[official documentation](https://github.com/cakephp/authorization/blob/master/docs/Middleware.md) +[official documentation](https://github.com/cakephp/authorization/blob/master/docs/Middleware.md). +The `CakeDC/Users.DefaultRedirect` allows the option 'url' to be a normal cake url or callback to let +you create a custom logic to retrieve the unauthorized redirect url. +``` +[ + 'unauthorizedHandler' => [ + 'className' => 'CakeDC/Users.DefaultRedirect', + 'url' => [ + 'plugin' => false, + 'prefix' => false, + 'controller' => 'Pages', + 'action' => 'home' + ] + ] +], +``` +OR +``` +[ + 'unauthorizedHandler' => [ + 'className' => 'CakeDC/Users.DefaultRedirect', + 'url' => function($request, $options) { + //custom logic + + return $url; + } + ] +], +``` Authorization Component ----------------------- We autoload the authorization component at users controller using the default configuration, From 94cbc2d8451e91a41ddd2c6be9052d89bb921989 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Thu, 20 Feb 2020 16:36:28 +0300 Subject: [PATCH 528/685] update composer config --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c848d80fd..2528d3491 100644 --- a/composer.json +++ b/composer.json @@ -85,7 +85,7 @@ "test": "phpunit --stderr", "stan": "phpstan analyse src/", "psalm": "php vendor/psalm/phar/psalm.phar --show-info=false src/ ", - "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12 psalm/phar:^3.5 && mv composer.backup composer.json", + "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12.0 psalm/phar:^3.7 && mv composer.backup composer.json", "stan-rebuild-baseline": "phpstan analyse --configuration phpstan.neon --error-format baselineNeon src/ > phpstan-baseline.neon", "psalm-rebuild-baseline": "php vendor/psalm/phar/psalm.phar --show-info=false --set-baseline=psalm-baseline.xml src/", "rector": "rector process src/", From 4a220885f9e0cb64b47ae5390aaf7cd337c4a7f9 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 28 Feb 2020 09:27:55 -0300 Subject: [PATCH 529/685] Custom unauthorized handler with flash message --- .../DefaultRedirectHandler.php | 53 +++++++++++++++++++ .../Integration/LoginTraitIntegrationTest.php | 2 + 2 files changed, 55 insertions(+) diff --git a/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php index 99f3331c7..2c3d3d948 100644 --- a/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php +++ b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php @@ -13,11 +13,14 @@ namespace CakeDC\Users\Middleware\UnauthorizedHandler; +use Authorization\Exception\Exception; use Authorization\Exception\ForbiddenException; use Authorization\Exception\MissingIdentityException; use Authorization\Middleware\UnauthorizedHandler\CakeRedirectHandler; use Cake\Http\ServerRequest; +use Cake\Http\Session; use Cake\Routing\Router; +use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; /** @@ -42,8 +45,24 @@ class DefaultRedirectHandler extends CakeRedirectHandler ], 'queryParam' => 'redirect', 'statusCode' => 302, + 'flash' => [], ]; + /** + * @inheritDoc + */ + public function handle(Exception $exception, ServerRequestInterface $request, array $options = []): ResponseInterface + { + $options += $this->defaultOptions; + $response = parent::handle($exception, $request, $options); + $session = $request->getAttribute('session'); + if ($session instanceof Session) { + $this->addFlashMessage($session, $options); + } + + return $response; + } + /** * @inheritDoc */ @@ -64,4 +83,38 @@ protected function getUrl(ServerRequestInterface $request, array $options): stri return Router::url($url); } + + /** + * Add a flash message informing location is not authorized. + * + * @param \Cake\Http\Session $session The CakePHP session. + * @param array $options Defined options. + * + * @return void + */ + protected function addFlashMessage(Session $session, $options): void + { + $messages = (array)$session->read('Flash.flash'); + $messages[] = $this->createFlashMessage($options); + $session->write('Flash.flash', $messages); + } + + /** + * Create a flash message data. + * + * @param array $options Handler options + * @return array + */ + protected function createFlashMessage($options): array + { + $message = (array)($options['flash'] ?? []); + $message += [ + 'message' => __d('cake_d_c/users', 'You are not authorized to access that location.'), + 'key' => 'flash', + 'element' => 'flash/error', + 'params' => [], + ]; + + return $message; + } } diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index 4fe25fb29..0cf5b36cb 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -54,8 +54,10 @@ public function loginAsUserId($id) */ public function testRedirectToLogin() { + $this->enableRetainFlashMessages(); $this->get('/pages/home'); $this->assertRedirect('/login?redirect=http%3A%2F%2Flocalhost%2Fpages%2Fhome'); + $this->assertFlashMessage('You are not authorized to access that location.'); } /** From 6d34c0f5b5d2c110e84d9d5d7b60963ebe467992 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Mar 2020 09:53:22 -0300 Subject: [PATCH 530/685] phpstan fix --- phpstan-baseline.neon | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 2e679c318..91b752251 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -302,4 +302,7 @@ parameters: count: 1 path: src\Shell\UsersShell.php - + - + message: "#^Parameter \\#1 \\$message of method Cake\\\\Controller\\\\Controller\\:\\:log\\(\\)\\ expects string, Exception given.$#" + count: 1 + path: src\Controller\Traits\OneTimePasswordVerifyTrait.php From e5bfc54629114abeeeb22a57a3e4911d75125fdb Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Mar 2020 10:35:55 -0300 Subject: [PATCH 531/685] UserHelper::welcome should work with request's attribute 'identity' --- src/View/Helper/UserHelper.php | 12 +-- tests/TestCase/View/Helper/UserHelperTest.php | 73 ++++++++++--------- 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index 99d71cf4d..c228e6ab9 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -117,18 +117,18 @@ public function logout($message = null, $options = []) /** * Welcome display - * @return mixed + * @return string|null */ public function welcome() { - $userId = $this->getView()->getRequest()->getSession()->read('Auth.User.id'); - if (empty($userId)) { - return; + $identity = $this->getView()->getRequest()->getAttribute('identity'); + if (!$identity) { + return null; } $profileUrl = Configure::read('Users.Profile.route'); - $session = $this->getView()->getRequest()->getSession(); - $title = $session->read('Auth.User.first_name') ?: $session->read('Auth.User.username'); + $title = $identity['first_name'] ?? null; + $title = $title ?: ($identity['username'] ?? null); $title = is_array($title) ? '-' : (string)$title; $label = __d( 'cake_d_c/users', diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index ca3c48b05..c01948400 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -13,6 +13,7 @@ namespace CakeDC\Users\Test\TestCase\View\Helper; +use Authentication\Identity; use Cake\Core\Configure; use Cake\Http\ServerRequest; use Cake\I18n\I18n; @@ -160,28 +161,17 @@ public function testWelcome() 'action' => 'profile', ]); - $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')); - - $request = $this->getMockBuilder('Cake\Http\ServerRequest') - ->setMethods(['getSession']) - ->getMock(); - $request->expects($this->any()) - ->method('getSession') - ->will($this->returnValue($session)); - + $user = [ + 'id' => 2, + 'first_name' => 'John', + 'last_name' => 'Doe', + 'username' => 'j04n.d09' + ]; + $identity = new Identity($user); + $request = new ServerRequest(); + $request = $request->withAttribute('identity', $identity); $this->User->getView()->setRequest($request); - $expected = 'Welcome, david'; + $expected = 'Welcome, John'; $result = $this->User->welcome(); $this->assertEquals($expected, $result); } @@ -191,23 +181,36 @@ public function testWelcome() * * @return void */ - public function testWelcomeNotLoggedInUser() + public function testWelcomeWillDisplayUsernameInstead() { - $session = $this->getMockBuilder('Cake\Http\Session') - ->setMethods(['read']) - ->getMock(); - $session->expects($this->at(0)) - ->method('read') - ->with('Auth.User.id') - ->will($this->returnValue(null)); + Router::connect('/profile', [ + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'profile', + ]); - $request = $this->getMockBuilder('Cake\Http\ServerRequest') - ->setMethods(['getSession']) - ->getMock(); - $request->expects($this->any()) - ->method('getSession') - ->will($this->returnValue($session)); + $user = [ + 'id' => 2, + 'last_name' => 'Doe', + 'username' => 'j04n.d09' + ]; + $identity = new Identity($user); + $request = new ServerRequest(); + $request = $request->withAttribute('identity', $identity); + $this->User->getView()->setRequest($request); + $expected = 'Welcome, j04n.d09'; + $result = $this->User->welcome(); + $this->assertEquals($expected, $result); + } + /** + * Test link + * + * @return void + */ + public function testWelcomeNotLoggedInUser() + { + $request = new ServerRequest(); $this->User->getView()->setRequest($request); $result = $this->User->welcome(); $this->assertEmpty($result); From 2059d5ee34da0433194d4ed50a5581e9c311960d Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Mar 2020 10:41:13 -0300 Subject: [PATCH 532/685] UserHelper::welcome should work with request's attribute 'identity' --- .../Traits/Integration/ProfileTraitIntegrationTest.php | 1 + .../Traits/Integration/SimpleCrudTraitIntegrationTest.php | 1 + tests/test_app/templates/layout/default.php | 1 + 3 files changed, 3 insertions(+) diff --git a/tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php index 8ee17b6dc..ea555a89d 100644 --- a/tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/ProfileTraitIntegrationTest.php @@ -63,6 +63,7 @@ public function testProfile() $this->assertResponseNotContains(''); $this->assertResponseNotContains('/link-social/amazon'); $this->assertResponseNotContains(''); + $this->assertResponseContains('Welcome, first1'); $this->get('/users/change-password'); $this->assertResponseOk(); diff --git a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php index 5317cde74..54d94f0a7 100644 --- a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php @@ -50,6 +50,7 @@ public function testCrud() $this->enableRetainFlashMessages(); $this->get('/users/index'); $this->assertResponseOk(); + $this->assertResponseContains('Welcome, user'); $this->assertResponseContains('New Users'); $this->assertResponseContains(''); $this->assertResponseContains(''); diff --git a/tests/test_app/templates/layout/default.php b/tests/test_app/templates/layout/default.php index d576f14d1..3bf15b9f8 100644 --- a/tests/test_app/templates/layout/default.php +++ b/tests/test_app/templates/layout/default.php @@ -23,6 +23,7 @@
From f57a0895a97c4fe1c5f385459f4de9e98a52ed9d Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Mar 2020 10:42:26 -0300 Subject: [PATCH 533/685] phpcs fixes --- tests/TestCase/View/Helper/UserHelperTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index c01948400..447606b08 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -164,8 +164,8 @@ public function testWelcome() $user = [ 'id' => 2, 'first_name' => 'John', - 'last_name' => 'Doe', - 'username' => 'j04n.d09' + 'last_name' => 'Doe', + 'username' => 'j04n.d09', ]; $identity = new Identity($user); $request = new ServerRequest(); @@ -191,8 +191,8 @@ public function testWelcomeWillDisplayUsernameInstead() $user = [ 'id' => 2, - 'last_name' => 'Doe', - 'username' => 'j04n.d09' + 'last_name' => 'Doe', + 'username' => 'j04n.d09', ]; $identity = new Identity($user); $request = new ServerRequest(); From b04928669674374f482aafe5a8c04239e96bcffc Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Mar 2020 11:06:22 -0300 Subject: [PATCH 534/685] stan fix --- phpstan-baseline.neon | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 91b752251..c670af94d 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -306,3 +306,8 @@ parameters: message: "#^Parameter \\#1 \\$message of method Cake\\\\Controller\\\\Controller\\:\\:log\\(\\)\\ expects string, Exception given.$#" count: 1 path: src\Controller\Traits\OneTimePasswordVerifyTrait.php + + - + message: "#^Access to an undefined property CakeDC\\\\Users\\\\View\\\\Helper\\\\AuthLinkHelper\\:\\:\\$Form\\.$#" + count: 1 + path: src\View\Helper\AuthLinkHelper.php From 8d4c3ff501ae9b85878dc18b42524464f3a3d4b7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 3 Mar 2020 11:07:56 -0300 Subject: [PATCH 535/685] removed warning from develop branch --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index 41b41eb0b..4dda62f2d 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,6 @@ CakeDC Users Plugin [![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) -Warning -------- - -**OUTDATED branch, please use the specific develop branch for each version, for example 8.x for the version 8 development** - - Versions and branches --------------------- @@ -38,7 +32,7 @@ It covers the following features: * Remember me (Cookie) via https://github.com/CakeDC/auth * Manage user's profile * Admin management -* Yubico U2F for Two-Factor Authentication +* Yubico U2F for Two-Factor Authentication * One-Time Password for Two-Factor Authentication The plugin is here to provide users related features following 2 approaches: From e1bd609792229e018d17c5a8b89fa9adeb487fce Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 4 Mar 2020 08:17:05 -0300 Subject: [PATCH 536/685] Authorization doc now mention flash message for unauthorized actions --- Docs/Documentation/Authorization.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md index 9869983a3..f17ef16ff 100644 --- a/Docs/Documentation/Authorization.md +++ b/Docs/Documentation/Authorization.md @@ -32,7 +32,7 @@ The default configuration for authorization middleware is: You can check the configuration options available for authorization middleware at the [official documentation](https://github.com/cakephp/authorization/blob/master/docs/Middleware.md). -The `CakeDC/Users.DefaultRedirect` allows the option 'url' to be a normal cake url or callback to let +The `CakeDC/Users.DefaultRedirect` offers additional config, you can customize the flash message and set 'url' as a normal cake url or callback to let you create a custom logic to retrieve the unauthorized redirect url. ``` @@ -44,7 +44,13 @@ you create a custom logic to retrieve the unauthorized redirect url. 'prefix' => false, 'controller' => 'Pages', 'action' => 'home' - ] + ], + 'flash' => [ + 'message' => 'My custom message', + 'key' => 'flash', + 'element' => 'flash/error', + 'params' => [], + ], ] ], ``` @@ -57,7 +63,13 @@ OR //custom logic return $url; - } + }, + 'flash' => [ + 'message' => 'My custom message', + 'key' => 'flash', + 'element' => 'flash/error', + 'params' => [], + ], ] ], ``` From a18eee91f632e2e80d6ce699da84d731eafe522e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 4 Mar 2020 08:23:49 -0300 Subject: [PATCH 537/685] Authorization doc now mention unauthorized behavior --- Docs/Documentation/Authorization.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md index f17ef16ff..d4714413b 100644 --- a/Docs/Documentation/Authorization.md +++ b/Docs/Documentation/Authorization.md @@ -32,8 +32,14 @@ The default configuration for authorization middleware is: You can check the configuration options available for authorization middleware at the [official documentation](https://github.com/cakephp/authorization/blob/master/docs/Middleware.md). -The `CakeDC/Users.DefaultRedirect` offers additional config, you can customize the flash message and set 'url' as a normal cake url or callback to let -you create a custom logic to retrieve the unauthorized redirect url. +The `CakeDC/Users.DefaultRedirect` offers additional behavior and config: + * If logged user access unauthorized url he is redirected to referer url or '/' if no referer url + * If not logged user access unauthorized url he is redirected to configured url (default to login) + * on login we only use the redirect url from querystring 'redirect' if user can access the target url + * App can configure a callbable for 'url' option to define a custom logic to retrieve the url for unauthorized redirect + * App can configure a flash message + +You could do the following to set a custom url and flash message: ``` [ From 23e2a62de7ef670798184240dedcb7a870c4437e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 4 Mar 2020 08:25:06 -0300 Subject: [PATCH 538/685] Getting ready to release 9.0.2 --- .semver | 2 +- CHANGELOG.md | 29 +++++++++++++++++++---------- Docs/Documentation/Authorization.md | 2 +- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.semver b/.semver index 1c2a8edb2..215c91863 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 9 :minor: 0 -:patch: 0 +:patch: 2 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index 08d4d0a3e..03d173221 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,20 @@ Changelog ========= Releases for CakePHP 4 ------------- +* 9.0.2 + * Added a custom Unauthorized Handler + * If logged user access unauthorized url he is redirected to referer url or '/' if no referer url + * If not logged user access unauthorized url he is redirected to configured url (default to login) + * on login we only use the redirect url from querystring 'redirect' if user can access the target url + * App can configure a callable for 'url' option to define a custom logic to retrieve the url for unauthorized redirect + * Added postLink method to AuthLinkHelper + * UserHelper::welcome now works with request's attribute 'identity' + * 9.0.1 * Improved routes * Improved integration tests * Fixed warnings related to arguments in function calls - + * 9.0.0 * Migration to CakePHP 4 * Compatible with cakephp/authentication @@ -27,7 +36,7 @@ Releases for CakePHP 3 * 8.4.0 * Rehash password if needed at login - + * 8.3.0 * Bootstrap don't need to listen for EVENT_FAILED_SOCIAL_LOGIN @@ -44,7 +53,7 @@ Releases for CakePHP 3 * Updated to latest version of Google OAuth * Added plugin object * Fixed action changePassword to work with post or put request - + * 8.0.2 * Add default role for users registered via social login @@ -59,14 +68,14 @@ Releases for CakePHP 3 * Added new translations * Improved customization options for recaptcha integration -* 7.0.2 +* 7.0.2 * Fixed an issue with 2FA only working on the second try -* 7.0.1 +* 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` @@ -79,7 +88,7 @@ Releases for CakePHP 3 * Updated Facebook Graph version to 2.8 * Fixed flash error messages on logic * Added link social account feature for twitter - * Switched to codecov + * Switched to codecov * 5.2.0 * Compatible with 3.5, deprecations will be removed in next major version of the plugin @@ -131,7 +140,7 @@ Releases for CakePHP 3 * 4.1.2 * Fix RememberMe redirect * Fix AuthLink rendering inside Cells - + * 4.1.1 * Add missing password field in add user @@ -148,7 +157,7 @@ Releases for CakePHP 3 * Fixed RegisterBehavior api, make getRegisterValidators public. * 3.2.3 - * Added compatibility with CakePHP 3.3+ + * Added compatibility with CakePHP 3.3+ * Fixed several bugs, including regression issue with Facebook login & improvements * 3.2.2 @@ -161,7 +170,7 @@ Releases for CakePHP 3 * 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 diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md index d4714413b..6575d2d56 100644 --- a/Docs/Documentation/Authorization.md +++ b/Docs/Documentation/Authorization.md @@ -36,7 +36,7 @@ The `CakeDC/Users.DefaultRedirect` offers additional behavior and config: * If logged user access unauthorized url he is redirected to referer url or '/' if no referer url * If not logged user access unauthorized url he is redirected to configured url (default to login) * on login we only use the redirect url from querystring 'redirect' if user can access the target url - * App can configure a callbable for 'url' option to define a custom logic to retrieve the url for unauthorized redirect + * App can configure a callable for 'url' option to define a custom logic to retrieve the url for unauthorized redirect * App can configure a flash message You could do the following to set a custom url and flash message: From bace4d076a5ff50eaf4aaa803225f11f4b8d2494 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 4 Mar 2020 08:26:40 -0300 Subject: [PATCH 539/685] Getting ready to release 9.0.2 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4905cf33e..f3c950233 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.1 | stable | -| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.1 | stable | +| ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.2 | stable | +| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.2 | stable | | ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | | 3.7 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | From ca86b0a7fe460c5edcfc75c31924227b4961fe84 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Wed, 1 Apr 2020 19:29:28 +0300 Subject: [PATCH 540/685] Formating code --- Docs/Documentation/Events.md | 37 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md index 5d1624e3a..d407316aa 100644 --- a/Docs/Documentation/Events.md +++ b/Docs/Documentation/Events.md @@ -16,22 +16,21 @@ The events in this plugin follow these conventions `.eventManager()->on(Plugin::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'); -} -``` + /** + * beforeRegister event + */ + public function eventRegister() + { + $this->eventManager()->on(Plugin::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'); + } From 0606dc402e81572157550ab23c213617bb9118ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=AF=D1=80=D0=BE=D1=81=D0=BB=D0=B0=D0=B2?= Date: Fri, 3 Apr 2020 15:01:24 +0300 Subject: [PATCH 541/685] Ukrainian translation --- resources/locales/uk/uk.mo | Bin 0 -> 19296 bytes resources/locales/uk/uk.po | 800 +++++++++++++++++++++++++++++++++++++ 2 files changed, 800 insertions(+) create mode 100644 resources/locales/uk/uk.mo create mode 100644 resources/locales/uk/uk.po diff --git a/resources/locales/uk/uk.mo b/resources/locales/uk/uk.mo new file mode 100644 index 0000000000000000000000000000000000000000..f48207e69e7980503374d42d240585fab9e7f628 GIT binary patch literal 19296 zcmcJW3zS?%na8h+0ueAGs|YGL;So?~G6_*+l90r_2qqz$2LyR}Gks^KO;7jO-IHVl zF^>g;L?93nMV^AF>uZusLdc6%*Y&mTcCW{C*7bFC-Q(_YSy%V$VLcw%{r#)z-oCf{ z_9Q{KPpbd7>Q;UA)%U8eswY1=^Q4D7KKm(eq5SQuJ@5D6ZLj5vPyg#Y?`kj)o(hhF zZv>BmZw9{)z76~}*ae<3-qvSJW}-vM7k{fFQw;LpKM z@K@j&;5o0i^Irm9MEx>w8u&g?Pg&zzeAF2O;78(BZ#>XHx$IDEi~6oDI$b zr+}-$%fXL=6Tz>7TF1YDqVocHF8C6tdCz%+=Sfr(z&C*%;7Q@p~31J{Ewl1ebu~cNrLft3k=- zAgFo14W1AF2%HRxxcKM-#qU)PmxEfzjiA;SfZ}HW)Ot36n)h~4a=HVQ-ahMaH+UNL zgP`X926#I715o_^64ba~gBo`xMkPBs*I_sKR_fP-7lG?RjeiVW3Vs2c1^ynq4xG*+ zt^gkdF9E*`O0O@1EY%xNWde91sP=_?iT?XRx_GyPvWK1EB=GCt+rbw=@pm>#l$c z$?*|T{C*C+5c~!xy}kg-4*md2ev>gy>18P>dtC*J-(FDkN}%*V3{D3h1^MUwfGkAJO8+-Fya$8@?+}P+ynh1cfiHrq!5K`p6nqF2y?l>3W|OW)cSu0_JgNV=>p53-aiFOucKf9{wFAVUVgEqcZCdZ>R#$Iz}eta;4t_L@Jry$IP2Bm={TL{T@4~CFAs|DJ+A#9Kv?kp8JrEi z7UNTVSPatS1)%2t7%0E`BB=2{b$AiRr1cGe>i-xh`F$Hiq~3U(Mf1KBJQcjoVF1pe zz7~|-eI9%zcoaMt{0jIb@LQnhZ$S96%g=$=fPW3%3ZBJFSn=)$$Ad>4{v9Z~KLw?y z--24_87$&7@LizznG0SEE&8l*Q+j^@5v4czUDj@H z0uhP#36Ldu-vnjHzXR8RmtSt{4}*i${}DVBT=Z_%4BiNe{|7-I{46*d{1zyB}N3t0Rra62gZ{t`R|eARR-m(#%0sV@XEMQ;_zP;Vo66L=7m zU7S6`^M=4~Q1nMY@%JKl4tN@ilO0V0rJuzhOY&|2%ix0`q`cQ4bWGoS4=8yRKv?n~ z21D@spzL!xMu!V|eW2#KAH=o2Pdoe$D1H70JQsWkd>eSqY^%>JK=GLe-vo|;lE*i} z4}))*WBJ_<(&X(2SAs8sSAmP)WBubHQ0w|3DEsy1dLAn9IzY**7gYOp@OJPhsCCc8 z$PkS;1nT`BPQ@!(GI4d7?M z8^J^1_2AhHv2Cyn`rxlY*~NGkrFGu|{tftJ@H61ki!8mx2uJpJ6DYqO1WyM43WR0v zo8WTr^!Iw+D?rIqpS_gxDfg+uXAR{kN=X$yAG2U&aud%xDYCcyuKmj(q`e+jp9*Te zhbXd>Efjs`TJRnQCsE|1KILM{R!W5;{v->1zGNZ(p3T#CS9^;?Ovc0tRb@MQJ@EM= zGFAH>`f{JkK+N6d8Lmyb`k;GW z1`<}h`zgZ|`MG@XJjxErU6gAnofLf(H{MT?UZv~k)5pW>T;-GCILh6W$6TA>LCWKa z`b9i1cJ+I~2i&u45!3PRq`b-#!&QWC76DfaA(Z~1=cnakm6#37qDH|!#=i~0- zFQW$V3-0-I;0DSq6#2l(l<4ya5348_QsjU7yq)p^%5F+8Me(Uj`84IVlnzStIhBVc zuJRi26BNah=<^{Ss+2jDk5YC~UP)2R+D!Q@!7C^yQ8rQDN4c5uX38RpKJTS0q%5GUphTZDdAOBw z9i`|RA9Z*(cs*s1aslNpC^t~1Q1ltm*Nn4zdeIAs9N%TX z+8_FT`E_B@&guuWhXX;r&>7QQ@HCo_ue<#~-SM z<;I)g(ooqC9OM0AIc$1WDfQ%of{&E)ML+qTCHwQB9ragTi?wwim-APdsdxzdVz?e2 z2g7oZ8-S9Su!{^U)qJtf9~>$VmMUSzjI-S>ql0;Wr4@QP^x+mN?qPj^tg9tI7ZyU+ zc)ovY*N0I;yKd#M5~@E6G&36(CNgFsgOE~C_U85n#lFyAhOw+Km2**ju&FM^luL!s zkZBR^+)}YOUmoxqqe{hM*i-e_=d1nV(W8eN!d$W`G7RRD$fY!^l}r7>LKsv+zgiyl zgT5eN?1Vzpy*H0ln57{6An_uPAy+Y5$t>1zE3L$c!E&i5jF@tIcRY0Z%bIvdj9X{i zBa1X{AnTtyR4&6zLn8CS01M5w%y~weo&{?`?zu(M^YJ`SU$)zP`G#k{V;2lJNR1bkT0(F^A!_mdP+#Yr&<{HbNR|(As7yGv95YbgTrP(Z>dlyt(PMPxg5kRK2B;Z zXMMQFUsEovm&3|<7Zpv=iL5iOm&3WiV6~?|h+8b{M6JoJBW+JjeVkAunz8oc@D}%X zEebZ(;la>b97KXNPezW5S-ht&1qZRb7#lDqQt=imj_JEJRP~nRD-|tyQl!yIT6JmA z1WyICz*|zv5j3&krNpmQ3TJwVT{~H^3RjC_L!%}RmSRT%dM%anA4-VdMpdFkrRv2& zCwlOaCDF+41wo-;?5+~`OTE?t?2L`kNt1S@8iV^Ws5K#xFq$N_e?&waN$dJS1%VRz zG?ygX(;xQOmeBZ+no8JhaVWHLZP0~HYpnPY;ibX?EIB*enApo3e`2N!cX7-ylcqK{ z=_ums#ONkQhQ(kF{+sE>M#r7e9Jn_!3}QQKc_9mGX^gDY$6bub+V*IAA*~gYX6u$} z*=VRB&0eEj+BN~lMubSO8Qo(Rm8&%Oi@Z6tBVmQ)I-wE_oX=ZUF0EtdDtpVrUXqbw zPw4jqMVBxYNp5)2hdY}d1L43Lk}|r!i^Ua!kt8 zSM2hdy%9L{%KH0?d|y$4Q2C0t!sdU?sjcy)u=#BpNu_C2qES)S8Kui{=981b1t=ZH z4TsGmB;`i$PH)A~ngLRQ70NG7cw!R^bKRa2bd!^=B$Td|-FYjKe@|0B;^#`C-75zI zb}-W?7M|V3QY-5Vi{!CnHW_J==o=PNBPzi<_K^6U+nJpZ<7O>Orf!Y^osI6q7+>#f zqMJ*bRXjTCB?_)*8~)TY#h&YKW^8%c;9alcjiY%?{37blBH1}P?(k3!KRA>xO9UpB zH{bsJ4TH2*Y+JnNho;r_OtVSnu~{M1Tkf2CKu#4l#9c7ulJc!K%q5<;9Y9 zbvHC#ikUDa?pUJD+ZXC8RqTOimE8xhVY|N@b1?IiWsubgV!t7mYUv89UsB&a7zYN#?*CDpu+`$k)#1fe5|eHlwR9d>P6Knh8&)HprI z4i}$(Es^wj!h|K6iOFdjjxZcnV*&|}%@@~{HW>ZoixuvA+;xdz-K0BEQdopgF9znyYjZU#Njew(f zP2zD9iSVuiG@V?Mr_?YKY5ePr$N+P?b6 z+P>PJ`cCjbeRJ)AS9_#3Lgk=d`CL_cwa4|Y_FU~SFLuyppI_fXSDhiXS5d0%U1!>14V_7gcm&q8zr&POeIUrd>WZmMr)4SQJ7U9}My^y_!B#KXQ> zqgy-^9QNUn_aiWioLKA8`n^8H4p9z5VfavqEg!{N}20R5Ma^I(H{+NlG3G|5eALWex$yc z)xz55G5Z@Cz=RZ3-^R>XhA&;!_R@GHCb0vePIhVLSzRdH`7;w8)+dx{K)dH_?w z=@^XF*LPm(*Y8Go^*dPQT}GeA2M#zdu;%V=rE3pp)={YrO&IIh&4TwMZReVs(B}cj zqDXa>(>jA@oLOPEmH6%o8*7uDp}YD$PS@VzPB))5d+X2oQVW zP)oimQqEX>Uh3Ci2E*AVXB~kWbVpPv&u+DJ1G=zx6_D6Gzodox> z4>G|~<55w#aQaU3>KfyH0_th0jZerVV6rBi;6vZnvewnQ?mi=FgA8bF@ZLY2DLkDhZR=uOFktN!_3R+G%xbj z##Tgb_khA98rvZsH32&DgH!Fxn5niwV=tQwJBf{4JEDY(J?}Qb$?bUcZ8k@gG9{Az z2t|pUq9Tu^a3;vf50r4->w=s_=XUnzWon5OkBaKVi`woE>+wA9)y^sBsNZF`7VRC4 zZP-{_I;NSXIHDO7Obi&|R2}`!CF@MQG6R#_wuI(S7K_G=nj@;|pUC2xr)r_+2uYNz zs$Hg@h~^C|ja*d1gylw9jZ@avwb1K8?Rn`ndDy@*v_BI~*~ZvC(EYxw2DXosG0>;E zNmnmNnr*g_n$0oYoieIKij$ey{Hl$T-# z<|s14xt6()lQ$cvu_y#%ZR_~vHtfF4IBhls;?%QJ1(xhYoSBa4c(YZ)NoS_UAsYu- z<0)Ap`eWFPq}#HcJZZzDmGd6sb%(JZXH%KKJaV$gVh^Ef?{Xd+1t)W4JH8Q71fe%! zGC>M|9V0kK`;+@c`Gm$EA7d`gy3=QxH-fFZqRBK=RGqw_Xk@3zcR6G2=tL@eeA&u=2{-$7iq!b*Ff?f}^%OPpyNQpn0>yD{sB_G)$F`Ghkx2i=FVA7XCV-s%P zoub%*&Je8GW}`J^NBGE2(ekl2VJnJbkbwc>f#UjDca80(YA%As6fvG6D}vDRT&PCt zjBmA4x_Saa=0eInw97@tN+aA*x6eP-a14kk>CL>|kg-3RwTmRO@i=3Sx1z`rvND%u zQ@2S0c9OAGjpghud?~&pxKi4i$@y4Bi6DEd-%EXa$dlP_O_HlrmOFGV3c1oY_vl%& z=CZBLtO?GV4zz}A6Ihg~+Phu;&y~)S7?RQ*9fpmV8h^IYp*wq-nKkI6-H9t_4Z#ty zzUXvG7&Jd-(1{h1_SVe-)rLP^J>F$CmI~0$?Vsf|x)UqrP#fibnJK9Wj;uhFYc);x zvJG>-@8w;5J?uy;=q7&GFrld>Io|Ce(_V4n)iTDK)yZC*)weId9uBQTOtqZH_nr=aIUo3kqFNz zHqxY;Hqq1ykG8QJ#F)6Lzy<8jWiW8>vCcr4{SK48=-yNOwuv;2*xv{oimq`!=Jrag z0hT2q7p=J3G6$2#{-5q{#DsOlKjz2RF}Z6}Nt^VJ`@-x10(;58p3y1Zrdk46L+nV@ zEzpruq|3B2ZW=OKaj~Oijtquk-)IVw&Iy}Z+i+oa*gx^F)ET_m--)=?YAh_;cQIy{ zAB{DR-`d%KrX>3tmDl65Ut+m$ZF35xj^Yc4`O#UUAp*7|a>exLj zd#S5#;wJYMgg5pm(hc_)13u zve~9JlkVL}t<9uXDdfRKY?JWm*X09^%P5lN*6Hn_m~p%Bx4V_kUY4DFs}_=ZW{=Gz zv8&0bo9Al%6;|`swZ++&PVD%Ovxx^CE}BSUo5X8lK`dVbf~Lc9Ky1Y67qV%WR6 zyl^~b%IyU5lRpigsUOAklcbW-NPhf%1wRMIzgoHNk0FXak!Yx4$`gEZo8#J%gpCm9 wk6YXSEuwFY%_YHdA`{o#&9*gS$(?q4u4}nfHc|d@ZR}ZNd78rvLx| literal 0 HcmV?d00001 diff --git a/resources/locales/uk/uk.po b/resources/locales/uk/uk.po new file mode 100644 index 000000000..7d708dd2c --- /dev/null +++ b/resources/locales/uk/uk.po @@ -0,0 +1,800 @@ +# LANGUAGE translation of CakePHP Application +# Copyright YEAR NAME +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2019-01-10 14:38+0000\n" +"PO-Revision-Date: 2020-04-03 14:57+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=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n" +"X-Generator: Poedit 2.3\n" +"Last-Translator: \n" +"Language: uk\n" + +#: Controller/SocialAccountsController.php:50 +msgid "Account validated successfully" +msgstr "Обліковий запис успішно підтверджено" + +#: Controller/SocialAccountsController.php:52 +msgid "Account could not be validated" +msgstr "Не вдалося підтвердити обліковий запис" + +#: Controller/SocialAccountsController.php:55 +msgid "Invalid token and/or social account" +msgstr "Недійсний маркер та / або соціальний акаунт" + +#: Controller/SocialAccountsController.php:57;85 +msgid "Social Account already active" +msgstr "Соціальний акаунт вже активний" + +#: Controller/SocialAccountsController.php:59 +msgid "Social Account could not be validated" +msgstr "Не вдалося підтвердити соціальний обліковий запис" + +#: Controller/SocialAccountsController.php:78 +msgid "Email sent successfully" +msgstr "Електронна пошта відправлена успішно" + +#: Controller/SocialAccountsController.php:80 +msgid "Email could not be sent" +msgstr "Не вдалося надіслати електронну пошту" + +#: Controller/SocialAccountsController.php:83 +msgid "Invalid account" +msgstr "Недійсний обліковий запис" + +#: Controller/SocialAccountsController.php:87 +msgid "Email could not be resent" +msgstr "Не вдалося відіслати електронний лист" + +#: Controller/Traits/LinkSocialTrait.php:52 +msgid "Could not associate account, please try again." +msgstr "Неможливо пов’язати обліковий запис. Повторіть спробу." + +#: Controller/Traits/LinkSocialTrait.php:76 +msgid "Social account was associated." +msgstr "Соціальний акаунт успішно активовано." + +#: Controller/Traits/LoginTrait.php:73 +msgid "You've successfully logged out" +msgstr "Ви успішно вийшли" + +#: Controller/Traits/OneTimePasswordVerifyTrait.php:71 +msgid "Please enable Google Authenticator first." +msgstr "Спершу ввімкніть Google Authenticator." + +#: Controller/Traits/OneTimePasswordVerifyTrait.php:80 +msgid "Could not find user data" +msgstr "Не вдалося знайти дані користувача" + +#: Controller/Traits/OneTimePasswordVerifyTrait.php:116 +msgid "Could not verify, please try again" +msgstr "Неможливо підтвердити. Повторіть спробу" + +#: Controller/Traits/OneTimePasswordVerifyTrait.php:144 +msgid "Verification code is invalid. Try again" +msgstr "Код підтвердження недійсний. Спробуйте ще раз" + +#: Controller/Traits/PasswordManagementTrait.php:53;91 +#: Controller/Traits/ProfileTrait.php:53 +msgid "User was not found" +msgstr "Користувача не знайдено" + +#: Controller/Traits/PasswordManagementTrait.php:75;87;95 +msgid "Password could not be changed" +msgstr "Не вдалося змінити пароль" + +#: Controller/Traits/PasswordManagementTrait.php:83 +msgid "Password has been changed successfully" +msgstr "Пароль успішно змінено" + +#: Controller/Traits/PasswordManagementTrait.php:137 +msgid "Please check your email to continue with password reset process" +msgstr "Будь ласка, перевірте вашу електронну пошту для відновлення пароля" + +#: Controller/Traits/PasswordManagementTrait.php:140 Shell/UsersShell.php:247 +msgid "The password token could not be generated. Please try again" +msgstr "Не вдалося створити маркер пароля. Будь ласка спробуйте ще раз" + +#: Controller/Traits/PasswordManagementTrait.php:146 +#: Controller/Traits/UserValidationTrait.php:116 +msgid "User {0} was not found" +msgstr "Користувача {0} не знайдено" + +#: Controller/Traits/PasswordManagementTrait.php:148 +msgid "The user is not active" +msgstr "Користувач неактивний" + +#: Controller/Traits/PasswordManagementTrait.php:150 +#: Controller/Traits/UserValidationTrait.php:111;120 +msgid "Token could not be reset" +msgstr "Не вдалося скинути маркер" + +#: Controller/Traits/PasswordManagementTrait.php:174 +msgid "Google Authenticator token was successfully reset" +msgstr "Маркер Google Authenticator успішно скинуто" + +#: Controller/Traits/ProfileTrait.php:57 +msgid "Not authorized, please login first" +msgstr "Не дозволено, спочатку увійдіть" + +#: Controller/Traits/RegisterTrait.php:46 +msgid "You must log out to register a new user account" +msgstr "Ви повинні вийти з системи, щоб зареєструвати новий обліковий запис" + +#: Controller/Traits/RegisterTrait.php:75;99 +msgid "The user could not be saved" +msgstr "Користувача не вдалося зберегти" + +#: Controller/Traits/RegisterTrait.php:92 Loader/LoginComponentLoader.php:32 +msgid "Invalid reCaptcha" +msgstr "Недійсна reCaptcha" + +#: Controller/Traits/RegisterTrait.php:133 +msgid "You have registered successfully, please log in" +msgstr "Ви успішно зареєструвались, будь ласка, увійдіть" + +#: Controller/Traits/RegisterTrait.php:135 +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/UserValidationTrait.php:44 +msgid "User account validated successfully" +msgstr "Обліковий запис успішно підтверджено" + +#: Controller/Traits/UserValidationTrait.php:46 +msgid "User account could not be validated" +msgstr "Не вдалося підтвердити обліковий запис" + +#: Controller/Traits/UserValidationTrait.php:49 +msgid "User already active" +msgstr "Користувач вже активний" + +#: Controller/Traits/UserValidationTrait.php:55 +msgid "Reset password token was validated successfully" +msgstr "Маркер скидання пароля успішно перевірено" + +#: Controller/Traits/UserValidationTrait.php:63 +msgid "Reset password token could not be validated" +msgstr "Маркер скидання пароля не може бути перевірений" + +#: Controller/Traits/UserValidationTrait.php:67 +msgid "Invalid validation type" +msgstr "Недійсний тип перевірки" + +#: Controller/Traits/UserValidationTrait.php:70 +msgid "Invalid token or user account already validated" +msgstr "Недійсний маркер або обліковий запис користувача вже підтверджено" + +#: Controller/Traits/UserValidationTrait.php:76 +msgid "Token already expired" +msgstr "Маркер вже сплив" + +#: Controller/Traits/UserValidationTrait.php:106 +msgid "Token has been reset successfully. Please check your email." +msgstr "Маркер успішно скинуто. Будь ласка, перевірте свою електронну пошту." + +#: Controller/Traits/UserValidationTrait.php:118 +msgid "User {0} is already active" +msgstr "Користувач {0} вже активний" + +#: Loader/LoginComponentLoader.php:30 +msgid "Username or password is incorrect" +msgstr "Ім'я користувача або пароль невірні" + +#: Loader/LoginComponentLoader.php:51 +msgid "Could not proceed with social account. Please try again" +msgstr "" +"Не вдалось продовжити використання соціального облікового запису. Будь ласка " +"спробуйте ще раз" + +#: Loader/LoginComponentLoader.php:53 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Користувача ще не підтверджено. Будь ласка, перевірте вашу поштову скриньку " +"для інструкцій" + +#: Loader/LoginComponentLoader.php:57 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Ваш соціальний обліковий запис ще не перевірено. Будь ласка, перевірте вашу " +"поштову скриньку для інструкцій" + +#: Mailer/UsersMailer.php:33 +msgid "Your account validation link" +msgstr "Посилання для перевірки облікового запису" + +#: Mailer/UsersMailer.php:51 +msgid "{0}Your reset password link" +msgstr "{0} Ваше посилання для скидання пароля" + +#: Mailer/UsersMailer.php:74 +msgid "{0}Your social account validation link" +msgstr "{0} Посилання для перевірки облікового запису" + +#: Middleware/SocialAuthMiddleware.php:65 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Введіть адресу електронної пошти" + +#: Middleware/SocialAuthMiddleware.php:75 +msgid "Could not identify your account, please try again" +msgstr "Не вдалося визначити обліковий запис, будь ласка, спробуйте ще раз" + +#: Model/Behavior/AuthFinderBehavior.php:48 +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;138 +msgid "User not found" +msgstr "Користувача не знайдено" + +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112 +msgid "User account already validated" +msgstr "Обліковий запис користувача вже підтверджено" + +#: Model/Behavior/PasswordBehavior.php:67 +msgid "User not active" +msgstr "Користувач не активний" + +#: Model/Behavior/PasswordBehavior.php:143 +msgid "The current password does not match" +msgstr "Поточний пароль не збігається" + +#: Model/Behavior/PasswordBehavior.php:146 +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/RegisterBehavior.php:151 +msgid "This field is required" +msgstr "Це поле обов‘язкове" + +#: Model/Behavior/SocialAccountBehavior.php:102;129 +msgid "Account already validated" +msgstr "Обліковий запис вже підтверджено" + +#: Model/Behavior/SocialAccountBehavior.php:105;132 +msgid "Account not found for the given token and email." +msgstr "Не знайдено користувача з цим маркером та адресою електронної пошти." + +#: Model/Behavior/SocialBehavior.php:83 +msgid "Unable to login user with reference {0}" +msgstr "Не вдається ввійти за посиланням {0}" + +#: Model/Behavior/SocialBehavior.php:122 +msgid "Email not present" +msgstr "Електронна пошта відсутня" + +#: Model/Table/UsersTable.php:79 +msgid "Your password does not match your confirm password. Please try again" +msgstr "Ваш пароль не відповідає підтвердженню. Будь ласка, спробуйте ще раз" + +#: Model/Table/UsersTable.php:171 +msgid "Username already exists" +msgstr "Такий користувач вже існує" + +#: Model/Table/UsersTable.php:177 +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 "Додавання нового користувача superadmin для цілей тестування" + +#: 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 "Введіть ім'я користувача або email." + +#: 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 "Id: {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:17 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 +msgid "Actions" +msgstr "Дії" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:28 +#: Template/Users/view.ctp:23 +msgid "List Users" +msgstr "Перелік користувачів" + +#: Template/Users/add.ctp:21 Template/Users/register.ctp:18 +msgid "Add User" +msgstr "Створити користувача" + +#: Template/Users/add.ctp:23 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:22 Template/Users/login.ctp:20 +#: Template/Users/profile.ctp:30 Template/Users/register.ctp:20 +#: Template/Users/view.ctp:33 +msgid "Username" +msgstr "Iм'я користувача" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:21 Template/Users/view.ctp:35 +msgid "Email" +msgstr "Електронна пошта" + +#: Template/Users/add.ctp:25 Template/Users/login.ctp:21 +#: Template/Users/register.ctp:22 +msgid "Password" +msgstr "Пароль" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:27 +msgid "First name" +msgstr "Ім‘я" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:39 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:28 +msgid "Last name" +msgstr "Прізвище" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:54 +#: Template/Users/view.ctp:49;74 +msgid "Active" +msgstr "Активний" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:58 Template/Users/register.ctp:37 +#: 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:25 +msgid "Confirm password" +msgstr "Повторити пароль" + +#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 +msgid "Delete" +msgstr "Видалити" + +#: Template/Users/edit.ctp:24 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:34 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Редагувати користувача" + +#: Template/Users/edit.ctp:40 Template/Users/view.ctp:43 +msgid "Token" +msgstr "Маркер" + +#: Template/Users/edit.ctp:42 +msgid "Token expires" +msgstr "Маркер спилв" + +#: Template/Users/edit.ctp:45 +msgid "API token" +msgstr "Маркер API" + +#: Template/Users/edit.ctp:48 +msgid "Activation date" +msgstr "Дата активації" + +#: Template/Users/edit.ctp:51 +msgid "TOS date" +msgstr "Дата приймання умов" + +#: Template/Users/edit.ctp:64 +msgid "Reset Google Authenticator Token" +msgstr "Скинути маркер Google Authenticator" + +#: Template/Users/edit.ctp:70 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "Ви дійсно бажаєте скинути маркер для користувача \"{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 +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:30 +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 "Email або ім'я користувача" + +#: 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 "Id" + +#: 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" + +#: 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:46 +msgid "Sign in with" +msgstr "Увійти з використанням" + +#: View/Helper/UserHelper.php:103 +msgid "Logout" +msgstr "Вихiд" + +#: View/Helper/UserHelper.php:121 +msgid "Welcome, {0}" +msgstr "Вітаємо, {0}" + +#: View/Helper/UserHelper.php:151 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "reCaptcha не налаштовано! Налаштуйте Users.reCaptcha.key" + +#: View/Helper/UserHelper.php:215 +msgid "Connected with {0}" +msgstr "Під‘єднано до {0}" + +#: View/Helper/UserHelper.php:220 +msgid "Connect with {0}" +msgstr "Під‘єднати до {0}" From 6e13b90f78d16fcca5ddced02242833a80cc9fc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=AF=D1=80=D0=BE=D1=81=D0=BB=D0=B0=D0=B2?= Date: Fri, 3 Apr 2020 15:17:04 +0300 Subject: [PATCH 542/685] contributor name --- resources/locales/uk/uk.mo | Bin 19296 -> 19340 bytes resources/locales/uk/uk.po | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/locales/uk/uk.mo b/resources/locales/uk/uk.mo index f48207e69e7980503374d42d240585fab9e7f628..074b08d3ffcf5f69e3b09bafa3b84bef5fdd80bd 100644 GIT binary patch delta 1557 zcmXZce`w5c7{Kx8gqic>m|Pp?n3}Cj=X+nD&+|N==ez!smSd+Z*B_0D zU9^bAW{PYPk@Q(2HjH969>+qA<0|}(QS_#ZlwvoI#KhSm9<<>+T#vs5{qHfq`dKp&`cjI&%ohg!vPSe#`MO=d( z?8OM$oFdoos52(AhDH8d2~HvoBR@$yY67=#0lq^0 z|5n;yZfqrOZEY%Qr3E+!D^U{);bx5BIDCRy@f)<`Kb(s8 zT#?DR2(?3HSb#fF_dA1Lyn@RZJ^9RnBqeJh_lDbW0=D8~>_V-edXdN_e1|o7bTM;- z-}r~KB{R<$+O4>h_z2Pzd4SX?gQ&xtzJ#LCkA<8sJuLR{V7SZZL=*C^97e6+4m$8T zdTW7W8YxCPf@AL^aYrEHz8dfbF@)D9<+-6))g1)MJ~7GtpiwF3u{J>)8G z$M>j1>2-@VVHN5DeW(ehQC14NP-kfa>J^2N+N2fh@eZ<;hGk6BI@UzT*B9&{V|_hFyARfTwMf6`Y zju#oNeTy53(~6BhIAPS!cu?!7Z}?>Xn5dtu1y)1cSHi*@cEFA;aV zNS%nRY!D_iU>Ux~J`7J3apDkq;{w`o3DYn!Nu&^KFcL4DPNDAq29xn~ zlDMUffgiJU>_Yv*2-c;2I^|we2@&)bazg;90UC5HOpayUecj9f--!GabQBF;; z1NHk?Q7ib&&48+kWruNaCi*e2HEqGY%#UL*-oiCFjXpSo<2Z+Uz-j6qfj4nKKE_@Q z9|;Fbg%HB0Pu{7=)v!8Bd}W=W!E$!!Y#SWmG5z z^O$F#?spQ4@eJ;v^<;(tL5l1aNr80Sfc5wiJ5V#QWr$qId)S6enIinjQ~q(L{6&f> zX<0_^G$KWjD@aZKzYYEZ#sn&Y^C&KG&$2 z4eOZKVkJ(X-u*w+-YOye8uXx6_$&J2S{s$&dh^43%s6l=!=dcm)qc&xDzDPIb zp&l@S8sIWUU;yc9FD0X1kqgO5>ahz4kgddm@i`) zx(bbFatZZ&A5gnkibS{tNky$#E9$xj`*0dH^8z}J;z&2@=XX%AZqd}@bc;l>;NUT8 z6E!1eiw8I2yt)1zgjt1yJ3l3rkj$s2nz(W{bN{3??#^Mju-ms9BX5NfXa3P1m z7=zJrV?!79(I#v}eZQUPgO8A)WfrS2aI(k0#cFjqDobk|rOw!VXN9BOWp@-8S2?Sz O2mZvbOok<#O8yTFQog7F diff --git a/resources/locales/uk/uk.po b/resources/locales/uk/uk.po index 7d708dd2c..0ea72d3d8 100644 --- a/resources/locales/uk/uk.po +++ b/resources/locales/uk/uk.po @@ -1,19 +1,19 @@ -# LANGUAGE translation of CakePHP Application -# Copyright YEAR NAME +# Ukrainian translation of CakePHP Application +# Copyright 2020 Yaroslav Kontsevyi # msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "POT-Creation-Date: 2019-01-10 14:38+0000\n" "PO-Revision-Date: 2020-04-03 14:57+0300\n" -"Language-Team: LANGUAGE \n" +"Language-Team: CakeDC \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%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n" "X-Generator: Poedit 2.3\n" -"Last-Translator: \n" +"Last-Translator: Yaroslav Kontsevyi \n" "Language: uk\n" #: Controller/SocialAccountsController.php:50 From 016931d5c498fbefe7b5e5d4eb4490e0063dd862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=AF=D1=80=D0=BE=D1=81=D0=BB=D0=B0=D0=B2?= Date: Fri, 3 Apr 2020 15:31:02 +0300 Subject: [PATCH 543/685] contributor name --- Docs/Documentation/Translations.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Docs/Documentation/Translations.md b/Docs/Documentation/Translations.md index 41abc4e08..13f54f404 100644 --- a/Docs/Documentation/Translations.md +++ b/Docs/Documentation/Translations.md @@ -10,7 +10,8 @@ The Plugin is translated into several languages: * Polish (pl) by @joulbex * Hungarian (hu_HU) by @rrd108 * Italian (it) by @arturmamedov -* Turkish (tr_TR) by @sayinserdar +* Turkish (tr_TR) by @sayinserdar +* Ukrainian (uk) by @yarkm13 **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. From be55e2fda7d1ce3d0afd6c5e4cef6ddc50c42de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 3 Apr 2020 13:33:00 +0100 Subject: [PATCH 544/685] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03d173221..62596172f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ Changelog ========= Releases for CakePHP 4 ------------- +* Next + * Ukrainian (uk) by @yarkm13 + * 9.0.2 * Added a custom Unauthorized Handler * If logged user access unauthorized url he is redirected to referer url or '/' if no referer url From ccc83915ff12dd8ea7e20fcccaa8fb6efb411c29 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Sun, 5 Apr 2020 14:15:01 +0300 Subject: [PATCH 545/685] Update Home.md Incorrect link to SocialAuthentication.md --- Docs/Home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Home.md b/Docs/Home.md index 5e493cb19..4385e3494 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -18,7 +18,7 @@ Documentation * [SimpleRbacAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SimpleRbacAuthorize.md) * [SuperuserAuthorize](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/SuperuserAuthorize.md) * [Intercept Login Action](Documentation/InterceptLoginAction.md) -* [Social Authentication](Documentation/SocialAuthenticate.md) +* [Social Authentication](Documentation/SocialAuthentication.md) * [Google Authenticator](Documentation/Two-Factor-Authenticator.md) * [Yubico U2F](Documentation/Yubico-U2F.md) * [UserHelper](Documentation/UserHelper.md) From fe51c85e9f4330ee7d91fe2ccbdc461f687d7669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D0=BD=D1=86=D0=B5=D0=B2=D0=BE=D0=B8=CC=86=20?= =?UTF-8?q?=D0=AF=D1=80=D0=BE=D1=81=D0=BB=D0=B0=D0=B2?= Date: Wed, 8 Apr 2020 02:45:45 +0300 Subject: [PATCH 546/685] fixed filenames --- resources/locales/uk/{uk.mo => users.mo} | Bin resources/locales/uk/{uk.po => users.po} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename resources/locales/uk/{uk.mo => users.mo} (100%) rename resources/locales/uk/{uk.po => users.po} (100%) diff --git a/resources/locales/uk/uk.mo b/resources/locales/uk/users.mo similarity index 100% rename from resources/locales/uk/uk.mo rename to resources/locales/uk/users.mo diff --git a/resources/locales/uk/uk.po b/resources/locales/uk/users.po similarity index 100% rename from resources/locales/uk/uk.po rename to resources/locales/uk/users.po From 9a4855619bfdd4564aeec43d85a547d7d6a80e18 Mon Sep 17 00:00:00 2001 From: Maxime Date: Wed, 15 Apr 2020 11:05:39 +0200 Subject: [PATCH 547/685] Write AuthLink Helper documentation --- Docs/Documentation/AuthLinkHelper.md | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Docs/Documentation/AuthLinkHelper.md diff --git a/Docs/Documentation/AuthLinkHelper.md b/Docs/Documentation/AuthLinkHelper.md new file mode 100644 index 000000000..76c2a6055 --- /dev/null +++ b/Docs/Documentation/AuthLinkHelper.md @@ -0,0 +1,55 @@ +AuthLinkHelper +============= + +The AuthLink 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. +This helper provided two methods that allow you to hide or dispay links and postLinks based on the permissions file. +No more permissions check in your views ! If the permissions file is update, you do not have to replicate the permissions logic in the views. + +Setup +--------------- + +Enable the Helper in `src/view/AppView.php`: +```php +class AppView extends View +{ + public function initialize() + { + parent::initialize(); + $this->loadHelper('CakeDC/Users.AuthLink'); + } +} +``` + +Link +----------------- + +You can use this helper like the initial [cakePhp HtmlHelper link method](https://book.cakephp.org/4/en/views/helpers/html.html#creating-links) : + +In templates +```diff +- echo $this->Html->link(__d('cake_d_c/users', 'List Users'), ['action' => 'index']) ++ echo $this->AuthLink->link(__d('cake_d_c/users', 'List Users'), ['action' => 'index']) +``` + +PostLink +----------------- + +You can use this helper like the initial [cakePhp FormHelper postLink method](https://book.cakephp.org/4/en/views/helpers/form.html#creating-post-links) : + +In templates +```diff +- echo $this->Form->postLink(__d('cake_d_c/users', 'Delete'), ['action' => 'delete', $user->id], ['confirm' => __d('cake_d_c/users', 'Are you sure you want to delete # {0}?', $user->id)]) ++ echo $this->AuthLink->postLink(__d('cake_d_c/users', 'Delete'), ['action' => 'delete', $user->id], ['confirm' => __d('cake_d_c/users', 'Are you sure you want to delete # {0}?', $user->id)]) +``` + +Before and After +----------------- + +The link method allow you to add two additional parameters in the options array. +Those two parameters are `before` and `after` to quickly inject some html code in the link, like icons etc + +```php +echo $this->AuthLink->link(__d('cake_d_c/users', 'List Users'), ['action' => 'index', 'before' => '']); +``` + +Before and After are only implemented for the link method. From c7503387d8c9fe326afa65220ec370d07a64aef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Wed, 15 Apr 2020 10:28:35 +0100 Subject: [PATCH 548/685] Update Home.md --- Docs/Home.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Home.md b/Docs/Home.md index 4385e3494..bb757d6e2 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -22,6 +22,7 @@ Documentation * [Google Authenticator](Documentation/Two-Factor-Authenticator.md) * [Yubico U2F](Documentation/Yubico-U2F.md) * [UserHelper](Documentation/UserHelper.md) +* [AuthLinkHelper](Documentation/AuthLinkHelper.md) * [Events](Documentation/Events.md) * [Extending the Plugin](Documentation/Extending-the-Plugin.md) * [Translations](Documentation/Translations.md) From ca068ff329c96d9db878f2c6d8e8a80eb61e4798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= <613615+jtraulle@users.noreply.github.com> Date: Wed, 15 Apr 2020 17:34:58 +0200 Subject: [PATCH 549/685] Use newEmptyEntity() instead of newEntity([]) --- src/Controller/Traits/SimpleCrudTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/Traits/SimpleCrudTrait.php b/src/Controller/Traits/SimpleCrudTrait.php index fb49432d5..33346d298 100644 --- a/src/Controller/Traits/SimpleCrudTrait.php +++ b/src/Controller/Traits/SimpleCrudTrait.php @@ -64,7 +64,7 @@ public function add() { $table = $this->loadModel(); $tableAlias = $table->getAlias(); - $entity = $table->newEntity([]); + $entity = $table->newEmptyEntity(); $this->set($tableAlias, $entity); $this->set('tableAlias', $tableAlias); $this->set('_serialize', [$tableAlias, 'tableAlias']); From e73f8ca54423d2864e82d2b2aea301103a12e69b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= <613615+jtraulle@users.noreply.github.com> Date: Wed, 15 Apr 2020 17:38:30 +0200 Subject: [PATCH 550/685] Use newEmptyEntity() instead of newEntity([]) --- src/Controller/Traits/RegisterTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index f48c553cf..49b43d3be 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -50,7 +50,7 @@ public function register() } $usersTable = $this->getUsersTable(); - $user = $usersTable->newEntity([]); + $user = $usersTable->newEmptyEntity(); $validateEmail = (bool)Configure::read('Users.Email.validate'); $useTos = (bool)Configure::read('Users.Tos.required'); $tokenExpiration = Configure::read('Users.Token.expiration'); From 5047deab7bcb8a21bd435f39fa7d3c8807203e35 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 11 May 2020 13:36:09 -0300 Subject: [PATCH 551/685] Fix config key --- Docs/Documentation/Authorization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md index 6575d2d56..f3e14a276 100644 --- a/Docs/Documentation/Authorization.md +++ b/Docs/Documentation/Authorization.md @@ -130,5 +130,5 @@ class AppAuthorizationServiceLoader - Change the authorization service loader: ``` -Configure::write('Authorization.serviceLoader', \App\Loader\AppAuthorizationServiceLoader::class); +Configure::write('Auth.Authorization.serviceLoader', \App\Loader\AppAuthorizationServiceLoader::class); ``` From db37d897469690f803c31154431a447368e8d793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Thu, 11 Jun 2020 11:32:08 +0100 Subject: [PATCH 552/685] allow DebugKit to bypass auth --- config/permissions.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config/permissions.php b/config/permissions.php index abb75d2d0..3e9bc2369 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -128,5 +128,12 @@ 'controller' => 'Pages', 'action' => 'display', ], + [ + 'role' => '*', + 'plugin' => 'DebugKit', + 'controller' => '*', + 'action' => '*', + 'bypassAuth' => true, + ], ] ]; From 1da84a7fcaade44d8bf35cedbe5f41cc6203d937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Wed, 24 Jun 2020 12:19:59 +0200 Subject: [PATCH 553/685] Remove UserHelper::isAuthorized that has been deprecated since 3.2.1 --- src/View/Helper/UserHelper.php | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index bceedc811..eb6238e26 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -184,24 +184,6 @@ public function link($title, $url = null, array $options = []) 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) * From 18cbc2424e8793e6ddbc9370bc538172a5ee214f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 6 Jul 2020 14:34:54 +0100 Subject: [PATCH 554/685] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62596172f..30ee96d6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,12 @@ Changelog Releases for CakePHP 4 ------------- * Next + * + +* 9.0.3 * Ukrainian (uk) by @yarkm13 + * Docs improvements + * Fix DebugKit permissions issues * 9.0.2 * Added a custom Unauthorized Handler From 9e28b2ec685550cf6f40473803540bd075fe21b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 6 Jul 2020 14:35:15 +0100 Subject: [PATCH 555/685] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index 215c91863..caf33d9cb 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 9 :minor: 0 -:patch: 2 +:patch: 3 :special: '' From 06a0598b860d364366ff4f4d123835125863e0d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Mon, 6 Jul 2020 14:36:17 +0100 Subject: [PATCH 556/685] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f3c950233..8da84a4e4 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.2 | stable | -| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.2 | stable | +| ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.3 | stable | +| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.3 | stable | | ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | | 3.7 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | @@ -51,8 +51,8 @@ Another decision made was limiting the plugin dependencies on other packages as Requirements ------------ -* CakePHP 3.6.0+ -* PHP 5.6+ +* CakePHP 4.0+ +* PHP 7.2+ Documentation ------------- From 5d0575f194a2425ef5172e1389974156583b6456 Mon Sep 17 00:00:00 2001 From: Marc Wilhelm Date: Mon, 6 Jul 2020 16:20:38 +0200 Subject: [PATCH 557/685] Update CakePHP versions for development branch --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8da84a4e4..d230e53be 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Versions and branches | ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.3 | stable | | ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.3 | stable | | ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | -| 3.7 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | +| ^3.7 <4.0 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | | 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | | 3.4 | [5.x](https://github.com/cakedc/users/tree/5.x) | 5.2.0 | stable | From b7c0fffd0762d6aaae4641463d38ae27add40d1b Mon Sep 17 00:00:00 2001 From: vagrant Date: Mon, 20 Jul 2020 02:01:39 +0000 Subject: [PATCH 558/685] fixup i18n domain --- src/Controller/Traits/PasswordManagementTrait.php | 2 +- tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 1dd7de656..5f4112188 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -59,7 +59,7 @@ public function changePassword($id = null) $redirect = Configure::read('Users.Profile.route'); } else { $this->Flash->error( - __d('CakeDC/Users', 'Changing another user\'s password is not allowed') + __d('cake_d_c/users', 'Changing another user\'s password is not allowed') ); $this->redirect(Configure::read('Users.Profile.route')); diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php index 0a4eba8ac..aa13b5bf8 100644 --- a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php @@ -269,7 +269,7 @@ public function testlinkSocialAccountFacebookProviderAccountExists($data, $userI $this->assertFalse($resultUser->has('social_accounts')); $expected = [ 'social_accounts' => [ - '_existsIn' => __d('cake_d_c/Users', 'Social account already associated to another user'), + '_existsIn' => __d('cake_d_c/users', 'Social account already associated to another user'), ], ]; $actual = $user->getErrors(); From 57ab46cfdbeb0e9620b213e360688112af0ee853 Mon Sep 17 00:00:00 2001 From: Chris Hallgren Date: Mon, 3 Aug 2020 03:37:42 -0500 Subject: [PATCH 559/685] Fixing issue where RememberMe cookie Remember me cookie would expire at the end of session because the expected parameter was `expire` and the config file has `expires` so cookies would expire at the end of the session. --- config/users.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/users.php b/config/users.php index dc491b080..b1f0cf038 100644 --- a/config/users.php +++ b/config/users.php @@ -92,7 +92,7 @@ 'Cookie' => [ 'name' => 'remember_me', 'Config' => [ - 'expires' => '1 month', + 'expire' => new DateTime('+1 month'), 'httpOnly' => true, ] ] @@ -150,7 +150,7 @@ 'skipTwoFactorVerify' => true, 'rememberMeField' => 'remember_me', 'cookie' => [ - 'expires' => '1 month', + 'expire' => new DateTime('+1 month'), 'httpOnly' => true, ], 'urlChecker' => 'Authentication.CakeRouter', From c5bb4d2966084dc9213fdca76f93e3bcff39f5a7 Mon Sep 17 00:00:00 2001 From: Chris Hallgren Date: Mon, 3 Aug 2020 03:43:28 -0500 Subject: [PATCH 560/685] Adding Slash per code review --- config/users.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/users.php b/config/users.php index b1f0cf038..3c535f7db 100644 --- a/config/users.php +++ b/config/users.php @@ -92,7 +92,7 @@ 'Cookie' => [ 'name' => 'remember_me', 'Config' => [ - 'expire' => new DateTime('+1 month'), + 'expire' => new \DateTime('+1 month'), 'httpOnly' => true, ] ] @@ -150,7 +150,7 @@ 'skipTwoFactorVerify' => true, 'rememberMeField' => 'remember_me', 'cookie' => [ - 'expire' => new DateTime('+1 month'), + 'expire' => new \DateTime('+1 month'), 'httpOnly' => true, ], 'urlChecker' => 'Authentication.CakeRouter', From 0d3e534a1e77c0fdaac037ce7177e657a3e8d0c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 8 Aug 2020 16:18:49 +0100 Subject: [PATCH 561/685] #fix-deprecations-tests fix deprecations and tests --- .travis.yml | 2 +- src/Model/Behavior/AuthFinderBehavior.php | 2 +- .../Controller/Traits/BaseTraitTest.php | 17 +++++++++++++++++ .../Controller/Traits/LinkSocialTraitTest.php | 1 + .../Controller/Traits/SimpleCrudTraitTest.php | 7 ++++++- .../Model/Behavior/RegisterBehaviorTest.php | 18 +++++++++--------- tests/TestCase/Model/Table/UsersTableTest.php | 10 +++++----- tests/TestCase/Shell/UsersShellTest.php | 2 +- 8 files changed, 41 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 10cad1063..9608f7102 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ dist: xenial php: - 7.2 - 7.3 - - '7.4snapshot' + - 7.4 sudo: false diff --git a/src/Model/Behavior/AuthFinderBehavior.php b/src/Model/Behavior/AuthFinderBehavior.php index 6add37b39..3dc19fe2b 100644 --- a/src/Model/Behavior/AuthFinderBehavior.php +++ b/src/Model/Behavior/AuthFinderBehavior.php @@ -51,7 +51,7 @@ public function findAuth(Query $query, array $options = []) $where = $query->clause('where') ?: []; $query ->where(function ($exp) use ($identifier, $where) { - $or = $exp->or_([$this->_table->aliasField('email') => $identifier]); + $or = $exp->or([$this->_table->aliasField('email') => $identifier]); return $or->add($where); }, [], true) diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index f97280c1a..a508795e3 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -24,12 +24,19 @@ use Cake\Mailer\Email; use Cake\Mailer\TransportFactory; use Cake\ORM\Entity; +use Cake\ORM\Table; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use CakeDC\Auth\Authentication\AuthenticationService; use CakeDC\Users\Model\Entity\User; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit_Framework_MockObject_RuntimeException; +/** + * Class BaseTraitTest + * @package CakeDC\Users\Test\TestCase\Controller\Traits + * + */ abstract class BaseTraitTest extends TestCase { /** @@ -56,6 +63,16 @@ abstract class BaseTraitTest extends TestCase public $loginAction = '/login-page'; + /** + * @var MockObject + */ + public $Trait; + + /** + * @var Table + */ + public $table; + /** * SetUp and create Trait * diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 94371c5ba..9c5212c62 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -20,6 +20,7 @@ use Cake\Http\ServerRequestFactory; use Cake\I18n\Time; use Cake\ORM\TableRegistry; +use CakeDC\Users\Model\Table\UsersTable; use League\OAuth2\Client\Provider\FacebookUser; use Zend\Diactoros\Uri; diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php index 9351a769c..1a302095d 100644 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -15,7 +15,12 @@ use Cake\Datasource\Exception\InvalidPrimaryKeyException; use Cake\Datasource\Exception\RecordNotFoundException; +use CakeDC\Users\Controller\Traits\SimpleCrudTrait; +/** + * Class SimpleCrudTraitTest + * @package CakeDC\Users\Test\TestCase\Controller\Traits + */ class SimpleCrudTraitTest extends BaseTraitTest { public $viewVars; @@ -127,7 +132,7 @@ public function testAddGet() $this->_mockRequestGet(); $this->Trait->add(); $expected = [ - 'Users' => $this->table->newEntity([]), + 'Users' => $this->table->newEmptyEntity(), 'tableAlias' => 'Users', '_serialize' => [ 'Users', diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index bdb843b23..c3cfbd780 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -92,7 +92,7 @@ public function testValidateRegisterNoValidateEmail() 'last_name' => 'user', 'tos' => 1, ]; - $result = $this->Table->register($this->Table->newEntity([]), $user, ['token_expiration' => 3600, 'validate_email' => 0]); + $result = $this->Table->register($this->Table->newEmptyEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 0]); $this->assertTrue($result->active); } @@ -104,7 +104,7 @@ public function testValidateRegisterNoValidateEmail() public function testValidateRegisterEmptyUser() { $user = []; - $result = $this->Table->register($this->Table->newEntity([]), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $result = $this->Table->register($this->Table->newEmptyEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); $this->assertFalse($result); } @@ -130,7 +130,7 @@ public function testValidateRegisterValidateEmailAndTos() 'last_name' => 'user', 'tos' => 1, ]; - $result = $this->Table->register($this->Table->newEntity([]), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $result = $this->Table->register($this->Table->newEmptyEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); $this->assertNotEmpty($result); $this->assertFalse($result->active); $this->assertNotEmpty($result->tos_date); @@ -177,7 +177,7 @@ public function testValidateRegisterValidatorOption() $this->Table->expects($this->once()) ->method('patchEntity') - ->with($this->Table->newEntity([]), $user, ['validate' => 'custom']) + ->with($this->Table->newEmptyEntity(), $user, ['validate' => 'custom']) ->will($this->returnValue($entityUser)); $this->Table->expects($this->once()) @@ -185,7 +185,7 @@ public function testValidateRegisterValidatorOption() ->with($entityUser) ->will($this->returnValue($entityUser)); - $result = $this->Behavior->register($this->Table->newEntity([]), $user, ['validator' => 'custom', 'validate_email' => 1]); + $result = $this->Behavior->register($this->Table->newEmptyEntity(), $user, ['validator' => 'custom', 'validate_email' => 1]); $this->assertNotEmpty($result->tos_date); } @@ -203,7 +203,7 @@ public function testValidateRegisterTosRequired() 'first_name' => 'test', 'last_name' => 'user', ]; - $result = $this->Table->register($this->Table->newEntity([]), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); + $result = $this->Table->register($this->Table->newEmptyEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); $this->assertFalse($result); } @@ -228,7 +228,7 @@ public function testValidateRegisterNoTosRequired() 'first_name' => 'test', 'last_name' => 'user', ]; - $result = $this->Table->register($this->Table->newEntity([]), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); + $result = $this->Table->register($this->Table->newEmptyEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); $this->assertNotEmpty($result); } @@ -313,7 +313,7 @@ public function testRegisterUsingDefaultRole() 'tos' => 1, ]; Configure::write('Users.Registration.defaultRole', false); - $result = $this->Table->register($this->Table->newEntity([]), $user, [ + $result = $this->Table->register($this->Table->newEmptyEntity(), $user, [ 'token_expiration' => 3600, 'validate_email' => 0, ]); @@ -337,7 +337,7 @@ public function testRegisterUsingCustomRole() 'tos' => 1, ]; Configure::write('Users.Registration.defaultRole', 'emperor'); - $result = $this->Table->register($this->Table->newEntity([]), $user, [ + $result = $this->Table->register($this->Table->newEmptyEntity(), $user, [ 'token_expiration' => 3600, 'validate_email' => 0, ]); diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index b3ef36c05..528be5977 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -85,7 +85,7 @@ public function testValidateRegisterNoValidateEmail() 'last_name' => 'user', 'tos' => 1, ]; - $result = $this->Users->register($this->Users->newEntity([]), $user, ['token_expiration' => 3600, 'validate_email' => 0]); + $result = $this->Users->register($this->Users->newEmptyEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 0]); $this->assertTrue($result->active); } @@ -97,7 +97,7 @@ public function testValidateRegisterNoValidateEmail() public function testValidateRegisterEmptyUser() { $user = []; - $result = $this->Users->register($this->Users->newEntity([]), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $result = $this->Users->register($this->Users->newEmptyEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); $this->assertFalse($result); } @@ -123,7 +123,7 @@ public function testValidateRegisterValidateEmail() 'last_name' => 'user', 'tos' => 1, ]; - $result = $this->Users->register($this->Users->newEntity([]), $user, ['token_expiration' => 3600, 'validate_email' => 1]); + $result = $this->Users->register($this->Users->newEmptyEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1]); $this->assertNotEmpty($result); $this->assertFalse($result->active); } @@ -141,7 +141,7 @@ public function testValidateRegisterTosRequired() 'first_name' => 'test', 'last_name' => 'user', ]; - $userEntity = $this->Users->newEntity([]); + $userEntity = $this->Users->newEmptyEntity(); $this->Users->register($userEntity, $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 1]); $this->assertEquals(['tos' => ['_required' => 'This field is required']], $userEntity->getErrors()); } @@ -166,7 +166,7 @@ public function testValidateRegisterNoTosRequired() 'first_name' => 'test', 'last_name' => 'user', ]; - $result = $this->Users->register($this->Users->newEntity([]), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); + $result = $this->Users->register($this->Users->newEmptyEntity(), $user, ['token_expiration' => 3600, 'validate_email' => 1, 'use_tos' => 0]); $this->assertNotEmpty($result); } diff --git a/tests/TestCase/Shell/UsersShellTest.php b/tests/TestCase/Shell/UsersShellTest.php index f3864c527..2ce3ea7c0 100644 --- a/tests/TestCase/Shell/UsersShellTest.php +++ b/tests/TestCase/Shell/UsersShellTest.php @@ -290,7 +290,7 @@ public function testResetAllPasswordsNoPassingParams() */ public function testResetPassword() { - $user = $this->Users->newEntity([]); + $user = $this->Users->newEmptyEntity(); $user->username = 'user-1'; $user->password = 'password'; From c0b85350294c3b19c9c73265f7c67caf6af0a26d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 8 Aug 2020 16:37:19 +0100 Subject: [PATCH 562/685] fix cs --- .gitignore | 1 + src/Authenticator/SocialAuthTrait.php | 1 - src/Controller/AppController.php | 1 - src/Controller/Component/LoginComponent.php | 2 -- .../Traits/CustomUsersTableTrait.php | 1 - src/Controller/Traits/LinkSocialTrait.php | 5 +--- .../Traits/OneTimePasswordVerifyTrait.php | 3 --- .../Traits/PasswordManagementTrait.php | 1 - src/Controller/Traits/ProfileTrait.php | 1 + src/Controller/Traits/U2fTrait.php | 1 - .../AccountAlreadyActiveException.php | 1 + src/Exception/AccountNotActiveException.php | 1 + src/Exception/MissingEmailException.php | 1 + src/Exception/TokenExpiredException.php | 1 + src/Exception/UserAlreadyActiveException.php | 1 + src/Exception/UserNotActiveException.php | 1 + src/Exception/UserNotFoundException.php | 1 + src/Exception/WrongPasswordException.php | 1 + src/Identifier/SocialIdentifier.php | 2 -- src/Loader/AuthenticationServiceLoader.php | 2 -- src/Loader/LoginComponentLoader.php | 1 - src/Loader/MiddlewareQueueLoader.php | 5 ---- src/Mailer/UsersMailer.php | 3 --- src/Middleware/SocialAuthMiddleware.php | 3 --- .../DefaultRedirectHandler.php | 1 - src/Model/Behavior/LinkSocialBehavior.php | 3 --- src/Model/Behavior/PasswordBehavior.php | 13 +++++----- src/Model/Behavior/RegisterBehavior.php | 6 ++--- src/Model/Behavior/SocialAccountBehavior.php | 8 +++--- src/Model/Behavior/SocialBehavior.php | 5 +--- src/Model/Entity/User.php | 1 + src/Model/Table/UsersTable.php | 4 +-- src/Plugin.php | 5 ++-- src/Shell/UsersShell.php | 1 - src/Traits/RandomStringTrait.php | 3 ++- src/Utility/UsersUrl.php | 2 -- src/View/Helper/UserHelper.php | 11 ++++---- tests/Fixture/PostsFixture.php | 1 - tests/Fixture/PostsUsersFixture.php | 1 - tests/Fixture/SocialAccountsFixture.php | 1 - tests/Fixture/UsersFixture.php | 1 - .../Authenticator/SocialAuthenticatorTest.php | 2 +- .../Component/SetupComponentTest.php | 1 + .../Controller/Traits/BaseTraitTest.php | 6 ++--- .../SimpleCrudTraitIntegrationTest.php | 6 ++--- .../Controller/Traits/LinkSocialTraitTest.php | 1 - .../Traits/OneTimePasswordVerifyTraitTest.php | 3 --- .../Traits/PasswordManagementTraitTest.php | 2 -- .../Controller/Traits/SimpleCrudTraitTest.php | 2 +- .../Controller/Traits/U2fTraitTest.php | 25 ++++++++----------- tests/TestCase/Mailer/UsersMailerTest.php | 1 - .../Middleware/SocialAuthMiddlewareTest.php | 4 +-- .../Model/Behavior/AuthFinderBehaviorTest.php | 1 - .../Model/Behavior/LinkSocialBehaviorTest.php | 3 --- .../Model/Behavior/PasswordBehaviorTest.php | 3 +-- .../Model/Behavior/RegisterBehaviorTest.php | 1 - .../Model/Behavior/SocialBehaviorTest.php | 6 ----- tests/TestCase/Model/Table/UsersTableTest.php | 1 - tests/TestCase/Utility/UsersUrlTest.php | 1 - tests/bootstrap.php | 2 +- .../TestApp/Controller/AppController.php | 1 - .../TestApp/Mailer/OverrideMailer.php | 2 +- 62 files changed, 61 insertions(+), 121 deletions(-) diff --git a/.gitignore b/.gitignore index c89d5a392..f696b2eed 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ composer.lock .php_cs* /coverage +.phpunit.result.cache diff --git a/src/Authenticator/SocialAuthTrait.php b/src/Authenticator/SocialAuthTrait.php index 9a0ff5b6a..cb3e7d1c0 100644 --- a/src/Authenticator/SocialAuthTrait.php +++ b/src/Authenticator/SocialAuthTrait.php @@ -24,7 +24,6 @@ trait SocialAuthTrait { /** * @param array $rawData social user raw data - * * @return \Authentication\Authenticator\Result */ protected function identify($rawData) diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index 9ede33800..68c4951e2 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -17,7 +17,6 @@ /** * AppController for Users Plugin - * */ class AppController extends BaseController { diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index 5db67b8d0..ad75f1b9d 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -82,7 +82,6 @@ public function handleLogin($errorOnlyPost, $redirectFailure) * Handle login failure * * @param bool $redirect should redirect? - * * @return \Cake\Http\Response|null */ public function handleFailure($redirect = true) @@ -165,7 +164,6 @@ protected function afterIdentifyUser($user) * @param \CakeDC\Auth\Authentication\AuthenticationService $service Authentication service * @param \CakeDC\Users\Model\Entity\User $user User entity. * @param \Cake\Http\ServerRequest $request The http request. - * * @return void */ protected function handlePasswordRehash($service, $user, \Cake\Http\ServerRequest $request) diff --git a/src/Controller/Traits/CustomUsersTableTrait.php b/src/Controller/Traits/CustomUsersTableTrait.php index 03d6c304e..c003996ca 100644 --- a/src/Controller/Traits/CustomUsersTableTrait.php +++ b/src/Controller/Traits/CustomUsersTableTrait.php @@ -19,7 +19,6 @@ /** * Customize Users Table - * */ trait CustomUsersTableTrait { diff --git a/src/Controller/Traits/LinkSocialTrait.php b/src/Controller/Traits/LinkSocialTrait.php index c706d2d25..a2fcf802f 100644 --- a/src/Controller/Traits/LinkSocialTrait.php +++ b/src/Controller/Traits/LinkSocialTrait.php @@ -19,7 +19,6 @@ /** * Actions to allow user to link social accounts - * */ trait LinkSocialTrait { @@ -27,7 +26,6 @@ trait LinkSocialTrait * Init link and auth process against provider * * @param string $alias of the provider. - * * @throws \Cake\Http\Exception\NotFoundException Quando o provider informado não existe * @return \Cake\Http\Response Redirects on successful */ @@ -50,7 +48,6 @@ public function linkSocial($alias = null) * 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 */ @@ -84,7 +81,7 @@ public function callbackLinkSocial($alias = null) } } catch (\Exception $e) { $log = sprintf( - "Error linking social account: %s %s", + 'Error linking social account: %s %s', $e->getMessage(), $e ); diff --git a/src/Controller/Traits/OneTimePasswordVerifyTrait.php b/src/Controller/Traits/OneTimePasswordVerifyTrait.php index ea827aa63..da3a963d8 100644 --- a/src/Controller/Traits/OneTimePasswordVerifyTrait.php +++ b/src/Controller/Traits/OneTimePasswordVerifyTrait.php @@ -104,7 +104,6 @@ protected function isVerifyAllowed() * Get the Google Authenticator secret of user, if not exists try to create one and save * * @param \CakeDC\Users\Model\Entity\User $user user data present on session - * * @return string if empty the creation has failed */ protected function onVerifyGetSecret($user) @@ -144,7 +143,6 @@ protected function onVerifyGetSecret($user) * Handle the action when user post the form with code * * @param array $loginAction url to login page used in redirect - * * @return \Cake\Http\Response */ protected function onPostVerifyCode($loginAction) @@ -178,7 +176,6 @@ protected function onPostVerifyCode($loginAction) * * @param array $loginAction url to login page used in redirect * @param \CakeDC\Users\Model\Entity\User $user user data present on session - * * @return \Cake\Http\Response */ protected function onPostVerifyCodeOkay($loginAction, $user) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 1dd7de656..5e53ff019 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -36,7 +36,6 @@ trait PasswordManagementTrait * reset password with session key (email token has already been validated) * * @param int|string|null $id user_id, null for logged in user id - * * @return mixed */ public function changePassword($id = null) diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index 1de0b787e..d2edc6586 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -27,6 +27,7 @@ trait ProfileTrait { /** * Profile action + * * @param mixed $id Profile id object. * @return mixed */ diff --git a/src/Controller/Traits/U2fTrait.php b/src/Controller/Traits/U2fTrait.php index 90f4151a4..b19370f76 100644 --- a/src/Controller/Traits/U2fTrait.php +++ b/src/Controller/Traits/U2fTrait.php @@ -30,7 +30,6 @@ trait U2fTrait * Perform redirect keeping current query string * * @param array $url base url - * * @return \Cake\Http\Response */ public function redirectWithQuery($url) diff --git a/src/Exception/AccountAlreadyActiveException.php b/src/Exception/AccountAlreadyActiveException.php index 879db6a7d..d938a749e 100644 --- a/src/Exception/AccountAlreadyActiveException.php +++ b/src/Exception/AccountAlreadyActiveException.php @@ -19,6 +19,7 @@ class AccountAlreadyActiveException extends Exception { /** * AccountAlreadyActiveException constructor. + * * @param array|string $message message * @param int $code code * @param null $previous previous diff --git a/src/Exception/AccountNotActiveException.php b/src/Exception/AccountNotActiveException.php index 1b8321cd7..1d9846a10 100644 --- a/src/Exception/AccountNotActiveException.php +++ b/src/Exception/AccountNotActiveException.php @@ -21,6 +21,7 @@ class AccountNotActiveException extends Exception /** * AccountNotActiveException constructor. + * * @param array|string $message message * @param int $code code * @param null $previous previous diff --git a/src/Exception/MissingEmailException.php b/src/Exception/MissingEmailException.php index 6faf65205..fb54ddf9f 100644 --- a/src/Exception/MissingEmailException.php +++ b/src/Exception/MissingEmailException.php @@ -19,6 +19,7 @@ class MissingEmailException extends Exception { /** * MissingEmailException constructor. + * * @param array|string $message message * @param int $code code * @param null $previous previous diff --git a/src/Exception/TokenExpiredException.php b/src/Exception/TokenExpiredException.php index eeb3fc974..1a40617f0 100644 --- a/src/Exception/TokenExpiredException.php +++ b/src/Exception/TokenExpiredException.php @@ -19,6 +19,7 @@ class TokenExpiredException extends Exception { /** * TokenExpiredException constructor. + * * @param array|string $message message * @param int $code code * @param null $previous previous diff --git a/src/Exception/UserAlreadyActiveException.php b/src/Exception/UserAlreadyActiveException.php index b3ad6794b..d7a62c921 100644 --- a/src/Exception/UserAlreadyActiveException.php +++ b/src/Exception/UserAlreadyActiveException.php @@ -19,6 +19,7 @@ class UserAlreadyActiveException extends Exception { /** * UserAlreadyActiveException constructor. + * * @param array|string $message message * @param int $code code * @param null $previous previous diff --git a/src/Exception/UserNotActiveException.php b/src/Exception/UserNotActiveException.php index c9a4c1d26..e82c41229 100644 --- a/src/Exception/UserNotActiveException.php +++ b/src/Exception/UserNotActiveException.php @@ -19,6 +19,7 @@ class UserNotActiveException extends Exception { /** * UserNotActiveException constructor. + * * @param array|string $message message * @param int $code code * @param null $previous previous diff --git a/src/Exception/UserNotFoundException.php b/src/Exception/UserNotFoundException.php index bafbbb679..0847369d8 100644 --- a/src/Exception/UserNotFoundException.php +++ b/src/Exception/UserNotFoundException.php @@ -19,6 +19,7 @@ class UserNotFoundException extends RecordNotFoundException { /** * UserNotFoundException constructor. + * * @param string $message message * @param int $code code * @param null $previous previous diff --git a/src/Exception/WrongPasswordException.php b/src/Exception/WrongPasswordException.php index 0d0494ca7..79a6979ff 100644 --- a/src/Exception/WrongPasswordException.php +++ b/src/Exception/WrongPasswordException.php @@ -19,6 +19,7 @@ class WrongPasswordException extends Exception { /** * WrongPasswordException constructor. + * * @param array|string $message message * @param int $code code * @param null $previous previous diff --git a/src/Identifier/SocialIdentifier.php b/src/Identifier/SocialIdentifier.php index 2448c3c0f..98248aee6 100644 --- a/src/Identifier/SocialIdentifier.php +++ b/src/Identifier/SocialIdentifier.php @@ -68,7 +68,6 @@ public function identify(array $credentials) * Get query object for fetching user from database. * * @param \Cake\Datasource\EntityInterface $user The user. - * * @return \Cake\ORM\Query */ protected function findUser($user) @@ -90,7 +89,6 @@ protected function findUser($user) * Create a new user or get if exists one for the social data * * @param mixed $data social data - * * @return mixed */ protected function createOrGetUser($data) diff --git a/src/Loader/AuthenticationServiceLoader.php b/src/Loader/AuthenticationServiceLoader.php index 1b99b3726..5ef982860 100644 --- a/src/Loader/AuthenticationServiceLoader.php +++ b/src/Loader/AuthenticationServiceLoader.php @@ -61,7 +61,6 @@ protected function loadIdentifiers($service) * Load the authenticators defined at config Auth.Authenticators * * @param \CakeDC\Auth\Authentication\AuthenticationService $service Authentication service to load identifiers - * * @return void */ protected function loadAuthenticators($service) @@ -79,7 +78,6 @@ protected function loadAuthenticators($service) * Load the CakeDC/Auth.TwoFactor based on config OneTimePasswordAuthenticator.login * * @param \CakeDC\Auth\Authentication\AuthenticationService $service Authentication service to load identifiers - * * @return void */ protected function loadTwoFactorAuthenticator($service) diff --git a/src/Loader/LoginComponentLoader.php b/src/Loader/LoginComponentLoader.php index f309d3be2..3d4b05bee 100644 --- a/src/Loader/LoginComponentLoader.php +++ b/src/Loader/LoginComponentLoader.php @@ -72,7 +72,6 @@ public static function forSocial($controller) * @param \Cake\Controller\Controller $controller Target controller * @param string $key configuration key * @param array $config base configuration - * * @return \CakeDC\Users\Controller\Component\LoginComponent|\Cake\Controller\Component * @throws \Exception */ diff --git a/src/Loader/MiddlewareQueueLoader.php b/src/Loader/MiddlewareQueueLoader.php index a1f4cca97..6b943870a 100644 --- a/src/Loader/MiddlewareQueueLoader.php +++ b/src/Loader/MiddlewareQueueLoader.php @@ -41,7 +41,6 @@ class MiddlewareQueueLoader * * @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to update. * @param \CakeDC\Users\Plugin $plugin Users plugin object - * * @return \Cake\Http\MiddlewareQueue */ public function __invoke(MiddlewareQueue $middlewareQueue, Plugin $plugin) @@ -57,7 +56,6 @@ public function __invoke(MiddlewareQueue $middlewareQueue, Plugin $plugin) * Load social middlewares if enabled. Based on config 'Users.Social.login' * * @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to update. - * * @return void */ protected function loadSocialMiddleware(MiddlewareQueue $middlewareQueue) @@ -74,7 +72,6 @@ protected function loadSocialMiddleware(MiddlewareQueue $middlewareQueue) * * @param \Cake\Http\MiddlewareQueue $middlewareQueue queue of middleware * @param \CakeDC\Users\Plugin $plugin Users plugin object - * * @return void */ protected function loadAuthenticationMiddleware(MiddlewareQueue $middlewareQueue, Plugin $plugin) @@ -87,7 +84,6 @@ protected function loadAuthenticationMiddleware(MiddlewareQueue $middlewareQueue * Load OneTimePasswordAuthenticatorMiddleware if enabled. Based on config 'OneTimePasswordAuthenticator.login' * * @param \Cake\Http\MiddlewareQueue $middlewareQueue queue of middleware - * * @return void */ protected function load2faMiddleware(MiddlewareQueue $middlewareQueue) @@ -105,7 +101,6 @@ protected function load2faMiddleware(MiddlewareQueue $middlewareQueue) * * @param \Cake\Http\MiddlewareQueue $middlewareQueue queue of middleware * @param \CakeDC\Users\Plugin $plugin Users plugin object - * * @return \Cake\Http\MiddlewareQueue */ protected function loadAuthorizationMiddleware(MiddlewareQueue $middlewareQueue, Plugin $plugin) diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 7e3ab2985..0091880b5 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -19,7 +19,6 @@ /** * User Mailer - * */ class UsersMailer extends Mailer { @@ -56,7 +55,6 @@ protected function validation(EntityInterface $user) * Send the reset password email to the user * * @param \Cake\Datasource\EntityInterface $user User entity - * * @return void */ protected function resetPassword(EntityInterface $user) @@ -88,7 +86,6 @@ protected function resetPassword(EntityInterface $user) * * @param \Cake\Datasource\EntityInterface $user User entity * @param \Cake\Datasource\EntityInterface $socialAccount SocialAccount entity - * * @return void */ protected function socialAccountValidation(EntityInterface $user, EntityInterface $socialAccount) diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 8548d433a..9abe7fc08 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -37,7 +37,6 @@ class SocialAuthMiddleware implements MiddlewareInterface * * @param \Cake\Http\ServerRequest $request The request. * @param \CakeDC\Users\Exception\SocialAuthenticationException $exception Exception thrown - * * @return \Psr\Http\Message\ResponseInterface A response */ protected function onAuthenticationException(ServerRequest $request, $exception) @@ -65,7 +64,6 @@ protected function onAuthenticationException(ServerRequest $request, $exception) * * @param \Cake\Http\ServerRequest $request the request with session attribute * @param string $message the message - * * @return void */ private function setErrorMessage(ServerRequest $request, $message) @@ -99,7 +97,6 @@ protected function responseWithActionLocation(Response $response, $action) * * @param \Cake\Http\ServerRequest $request The request * @param \Psr\Http\Server\RequestHandlerInterface $handler The request handler. - * * @return \Psr\Http\Message\ResponseInterface */ protected function goNext(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface diff --git a/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php index 2c3d3d948..5681be54c 100644 --- a/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php +++ b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php @@ -89,7 +89,6 @@ protected function getUrl(ServerRequestInterface $request, array $options): stri * * @param \Cake\Http\Session $session The CakePHP session. * @param array $options Defined options. - * * @return void */ protected function addFlashMessage(Session $session, $options): void diff --git a/src/Model/Behavior/LinkSocialBehavior.php b/src/Model/Behavior/LinkSocialBehavior.php index b88f03b72..a5f57a2cb 100644 --- a/src/Model/Behavior/LinkSocialBehavior.php +++ b/src/Model/Behavior/LinkSocialBehavior.php @@ -34,7 +34,6 @@ class LinkSocialBehavior extends Behavior * * @param \Cake\Datasource\EntityInterface $user User to link. * @param array $data Social account information. - * * @return \Cake\Datasource\EntityInterface */ public function linkSocialAccount(EntityInterface $user, $data) @@ -66,7 +65,6 @@ public function linkSocialAccount(EntityInterface $user, $data) * @param \Cake\Datasource\EntityInterface $user User to link. * @param array $data Social account information. * @param \Cake\Datasource\EntityInterface $socialAccount to update or create. - * * @return \Cake\Datasource\EntityInterface */ protected function createOrUpdateSocialAccount(EntityInterface $user, $data, $socialAccount) @@ -107,7 +105,6 @@ protected function createOrUpdateSocialAccount(EntityInterface $user, $data, $so * * @param \Cake\Datasource\EntityInterface $socialAccount to populate. * @param array $data Social account information. - * * @return \Cake\Datasource\EntityInterface */ protected function populateSocialAccount($socialAccount, $data) diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index a434b6008..52fb92a55 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -34,7 +34,6 @@ class PasswordBehavior extends BaseTokenBehavior * * @param string $reference User username or email * @param array $options checkActive, sendEmail, expiration - * * @return string * @throws \InvalidArgumentException * @throws \CakeDC\Users\Exception\UserNotFoundException @@ -43,29 +42,29 @@ class PasswordBehavior extends BaseTokenBehavior public function resetToken($reference, array $options = []) { if (empty($reference)) { - throw new \InvalidArgumentException(__d('cake_d_c/users', "Reference cannot be null")); + throw new \InvalidArgumentException(__d('cake_d_c/users', 'Reference cannot be null')); } $expiration = $options['expiration'] ?? null; if (empty($expiration)) { - throw new \InvalidArgumentException(__d('cake_d_c/users', "Token expiration cannot be empty")); + throw new \InvalidArgumentException(__d('cake_d_c/users', 'Token expiration cannot be empty')); } $user = $this->_getUser($reference); if (empty($user)) { - throw new UserNotFoundException(__d('cake_d_c/users', "User not found")); + throw new UserNotFoundException(__d('cake_d_c/users', 'User not found')); } if ($options['checkActive'] ?? false) { if ($user->active) { - throw new UserAlreadyActiveException(__d('cake_d_c/users', "User account already validated")); + throw new UserAlreadyActiveException(__d('cake_d_c/users', 'User account already validated')); } $user->active = false; $user->activation_date = null; } if ($options['ensureActive'] ?? false) { if (!$user['active']) { - throw new UserNotActiveException(__d('cake_d_c/users', "User not active")); + throw new UserNotActiveException(__d('cake_d_c/users', 'User not active')); } } $user->updateToken($expiration); @@ -136,7 +135,7 @@ public function changePassword(EntityInterface $user) 'contain' => [], ]); } catch (RecordNotFoundException $e) { - throw new UserNotFoundException(__d('cake_d_c/users', "User not found")); + throw new UserNotFoundException(__d('cake_d_c/users', 'User not found')); } if (!empty($user->current_password)) { diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 891b13566..e73b46cc0 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -89,10 +89,10 @@ public function validate($token, $callback = null) ->where(['token' => $token]) ->first() : null; if (empty($user)) { - throw new UserNotFoundException(__d('cake_d_c/users', "User not found for the given token and email.")); + throw new UserNotFoundException(__d('cake_d_c/users', 'User not found for the given token and email.')); } if ($user->tokenExpired()) { - throw new TokenExpiredException(__d('cake_d_c/users', "Token has already expired user with no token")); + throw new TokenExpiredException(__d('cake_d_c/users', 'Token has already expired user with no token')); } if (!method_exists($this, (string)$callback)) { return $user; @@ -111,7 +111,7 @@ public function validate($token, $callback = null) public function activateUser(EntityInterface $user) { if ($user->active) { - throw new UserAlreadyActiveException(__d('cake_d_c/users', "User account already validated")); + throw new UserAlreadyActiveException(__d('cake_d_c/users', 'User account already validated')); } $user->activation_date = new \DateTime(); $user->token_expires = null; diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 3fff00472..271533403 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -101,11 +101,11 @@ public function validateAccount($provider, $reference, $token) if (!empty($socialAccount) && $socialAccount->token === $token) { if ($socialAccount->active) { - throw new AccountAlreadyActiveException(__d('cake_d_c/users', "Account already validated")); + throw new AccountAlreadyActiveException(__d('cake_d_c/users', 'Account already validated')); } } else { throw new RecordNotFoundException( - __d('cake_d_c/users', "Account not found for the given token and email.") + __d('cake_d_c/users', 'Account not found for the given token and email.') ); } @@ -131,12 +131,12 @@ public function resendValidation($provider, $reference) if (!empty($socialAccount)) { if ($socialAccount->active) { throw new AccountAlreadyActiveException( - __d('cake_d_c/users', "Account already validated") + __d('cake_d_c/users', 'Account already validated') ); } } else { throw new RecordNotFoundException( - __d('cake_d_c/users', "Account not found for the given token and email.") + __d('cake_d_c/users', 'Account not found for the given token and email.') ); } diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 37ad1e291..693dc87e5 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -27,7 +27,6 @@ /** * Covers social features - * */ class SocialBehavior extends BaseTokenBehavior { @@ -213,7 +212,7 @@ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail $userData['password'] = $this->randomString(); $userData['avatar'] = $data['avatar'] ?? null; $userData['validated'] = !empty($dataValidated); - $userData['tos_date'] = date("Y-m-d H:i:s"); + $userData['tos_date'] = date('Y-m-d H:i:s'); $userData['gender'] = $data['gender'] ?? null; $userData['social_accounts'][] = $accountData; @@ -263,7 +262,6 @@ public function generateUniqueUsername($username) * * @param \Cake\ORM\Query $query The base query. * @param array $options Find options with email key. - * * @return \Cake\ORM\Query */ public function findExistingForSocialLogin(\Cake\ORM\Query $query, array $options) @@ -277,7 +275,6 @@ public function findExistingForSocialLogin(\Cake\ORM\Query $query, array $option * Extract the account data to insert/update * * @param array $data Social data. - * * @throws \Exception * @return array */ diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 45e162089..2e1e7e869 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -176,6 +176,7 @@ protected function _getU2fRegistration() /** * Generate token_expires and token in a user + * * @param int $tokenExpiration seconds to expire the token from Now * @return void */ diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 83c8ad049..089f88a9f 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -29,7 +29,6 @@ * @method \CakeDC\Users\Model\Entity\User patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = []) * @method \CakeDC\Users\Model\Entity\User[] patchEntities($entities, array $data, array $options = []) * @method \CakeDC\Users\Model\Entity\User findOrCreate($search, callable $callback = null, $options = []) - * * @mixin \CakeDC\Users\Model\Behavior\AuthFinderBehavior * @mixin \CakeDC\Users\Model\Behavior\LinkSocialBehavior * @mixin \CakeDC\Users\Model\Behavior\PasswordBehavior @@ -92,6 +91,7 @@ public function initialize(array $config): void /** * Adds some rules for password confirm + * * @param \Cake\Validation\Validator $validator Cake validator object. * @return \Cake\Validation\Validator */ @@ -179,8 +179,8 @@ public function validationDefault(Validator $validator): Validator /** * Wrapper for all validation rules for register - * @param \Cake\Validation\Validator $validator Cake validator object. * + * @param \Cake\Validation\Validator $validator Cake validator object. * @return \Cake\Validation\Validator */ public function validationRegister(Validator $validator) diff --git a/src/Plugin.php b/src/Plugin.php index 6b5fc5d91..8ad5ba6fd 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -57,7 +57,7 @@ public function getAuthenticationService(ServerRequestInterface $request): Authe } /** - * {@inheritdoc} + * @inheritDoc */ public function getAuthorizationService(ServerRequestInterface $request): AuthorizationServiceInterface { @@ -67,7 +67,7 @@ public function getAuthorizationService(ServerRequestInterface $request): Author } /** - * {@inheritdoc} + * @inheritDoc */ public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue { @@ -81,7 +81,6 @@ public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue * * @param \Psr\Http\Message\ServerRequestInterface $request The request. * @param string $loaderKey service loader key - * * @return mixed */ protected function loadService(ServerRequestInterface $request, $loaderKey) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 6446d09fa..89b62629f 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -38,7 +38,6 @@ class UsersShell extends Shell ]; /** - * * @return \Cake\Console\ConsoleOptionParser */ public function getOptionParser(): ConsoleOptionParser diff --git a/src/Traits/RandomStringTrait.php b/src/Traits/RandomStringTrait.php index e1703ad2d..6caffad7b 100644 --- a/src/Traits/RandomStringTrait.php +++ b/src/Traits/RandomStringTrait.php @@ -17,6 +17,7 @@ trait RandomStringTrait { /** * Generates random string + * * @param int $length String size. * @return string */ @@ -25,7 +26,7 @@ public function randomString($length = 10) if (!is_numeric($length) || $length <= 0) { $length = 10; } - $string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + $string = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; return substr(str_shuffle($string), 0, $length); } diff --git a/src/Utility/UsersUrl.php b/src/Utility/UsersUrl.php index 52fbd36b0..96d05151a 100644 --- a/src/Utility/UsersUrl.php +++ b/src/Utility/UsersUrl.php @@ -35,7 +35,6 @@ public static function isCustom() * * @param string $action user action * @param array $extra extra url attributes - * * @return array */ public static function actionUrl($action, $extra = []) @@ -83,7 +82,6 @@ public static function actionParams($action) * * @param string $action users action * @param \Cake\Http\ServerRequest $request the request - * * @return bool */ public static function checkActionOnRequest($action, ServerRequest $request) diff --git a/src/View/Helper/UserHelper.php b/src/View/Helper/UserHelper.php index c228e6ab9..ed05048e1 100644 --- a/src/View/Helper/UserHelper.php +++ b/src/View/Helper/UserHelper.php @@ -117,6 +117,7 @@ public function logout($message = null, $options = []) /** * Welcome display + * * @return string|null */ public function welcome() @@ -141,6 +142,7 @@ public function welcome() /** * Add reCaptcha script + * * @return void */ public function addReCaptchaScript() @@ -152,6 +154,7 @@ public function addReCaptchaScript() /** * Add reCaptcha to the form + * * @return mixed */ public function addReCaptcha() @@ -184,7 +187,6 @@ public function addReCaptcha() * 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. @@ -204,7 +206,6 @@ public function link($title, $url = null, array $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 */ @@ -224,7 +225,6 @@ public function isAuthorized($url = null) * @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) @@ -253,15 +253,14 @@ public function socialConnectLink($name, $provider, $isConnected = false) * 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 ""; + return ''; } - $html = ""; + $html = ''; $connectedProviders = array_map( function ($item) { return strtolower($item->provider); diff --git a/tests/Fixture/PostsFixture.php b/tests/Fixture/PostsFixture.php index 232178368..eb5fb9b7b 100644 --- a/tests/Fixture/PostsFixture.php +++ b/tests/Fixture/PostsFixture.php @@ -15,7 +15,6 @@ /** * PostsFixture - * */ class PostsFixture extends TestFixture { diff --git a/tests/Fixture/PostsUsersFixture.php b/tests/Fixture/PostsUsersFixture.php index 403639ee5..84cc2f1f8 100644 --- a/tests/Fixture/PostsUsersFixture.php +++ b/tests/Fixture/PostsUsersFixture.php @@ -15,7 +15,6 @@ /** * PostUsers Fixture - * */ class PostsUsersFixture extends TestFixture { diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php index f06ac1b6d..6200866f5 100644 --- a/tests/Fixture/SocialAccountsFixture.php +++ b/tests/Fixture/SocialAccountsFixture.php @@ -15,7 +15,6 @@ /** * AccountsFixture - * */ class SocialAccountsFixture extends TestFixture { diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index b7bb8e61f..607393d18 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -16,7 +16,6 @@ /** * UsersFixture - * */ class UsersFixture extends TestFixture { diff --git a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php index fdc3a86fa..981f63ea2 100644 --- a/tests/TestCase/Authenticator/SocialAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/SocialAuthenticatorTest.php @@ -492,6 +492,7 @@ public function testAuthenticateIdentifierReturnedNull() /** * Data provider for testAuthenticateErrorException + * * @return array */ public function dataProviderAuthenticateErrorException() @@ -513,7 +514,6 @@ public function dataProviderAuthenticateErrorException() * * @param \Exception $exception thrown exception * @param string $status expected status from Result object - * * @dataProvider dataProviderAuthenticateErrorException * @return void */ diff --git a/tests/TestCase/Controller/Component/SetupComponentTest.php b/tests/TestCase/Controller/Component/SetupComponentTest.php index 617a8db14..d685949a2 100644 --- a/tests/TestCase/Controller/Component/SetupComponentTest.php +++ b/tests/TestCase/Controller/Component/SetupComponentTest.php @@ -21,6 +21,7 @@ /** * Class SetupComponentTest + * * @package CakeDC\Users\Test\TestCase\Controller\Component */ class SetupComponentTest extends TestCase diff --git a/tests/TestCase/Controller/Traits/BaseTraitTest.php b/tests/TestCase/Controller/Traits/BaseTraitTest.php index a508795e3..693940e8a 100644 --- a/tests/TestCase/Controller/Traits/BaseTraitTest.php +++ b/tests/TestCase/Controller/Traits/BaseTraitTest.php @@ -24,18 +24,16 @@ use Cake\Mailer\Email; use Cake\Mailer\TransportFactory; use Cake\ORM\Entity; -use Cake\ORM\Table; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use CakeDC\Auth\Authentication\AuthenticationService; use CakeDC\Users\Model\Entity\User; -use PHPUnit\Framework\MockObject\MockObject; use PHPUnit_Framework_MockObject_RuntimeException; /** * Class BaseTraitTest - * @package CakeDC\Users\Test\TestCase\Controller\Traits * + * @package CakeDC\Users\Test\TestCase\Controller\Traits */ abstract class BaseTraitTest extends TestCase { @@ -93,7 +91,7 @@ public function setUp(): void ->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()"); + $this->fail('Unit tests extending BaseTraitTest should declare the trait class name in the $traitClassName variable before calling setUp()'); } if ($this->mockDefaultEmail) { diff --git a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php index 54d94f0a7..90df2fcc2 100644 --- a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php @@ -93,7 +93,7 @@ public function testCrud() $this->assertRedirect('/users/index'); $this->assertFlashMessage('Password has been changed successfully'); - $this->get("/users/edit/00000000-0000-0000-0000-000000000006"); + $this->get('/users/edit/00000000-0000-0000-0000-000000000006'); $this->assertResponseContains('assertResponseContains('List Users'); $this->enableSecurityToken(); - $this->post("/users/edit/00000000-0000-0000-0000-000000000006", [ + $this->post('/users/edit/00000000-0000-0000-0000-000000000006', [ 'username' => 'my-new-username', 'email' => 'crud.email992@example.com', 'first_name' => 'Joe', @@ -113,7 +113,7 @@ public function testCrud() ]); $this->assertRedirect('/users/index'); $this->assertFlashMessage('The User has been saved'); - $this->get("/users/view/00000000-0000-0000-0000-000000000006"); + $this->get('/users/view/00000000-0000-0000-0000-000000000006'); $this->assertResponseOk(); $this->assertResponseContains('>00000000-0000-0000-0000-000000000006<'); $this->assertResponseContains('>my-new-username<'); diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 9c5212c62..94371c5ba 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -20,7 +20,6 @@ use Cake\Http\ServerRequestFactory; use Cake\I18n\Time; use Cake\ORM\TableRegistry; -use CakeDC\Users\Model\Table\UsersTable; use League\OAuth2\Client\Provider\FacebookUser; use Zend\Diactoros\Uri; diff --git a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php index 168d137da..f6174ab00 100644 --- a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php +++ b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php @@ -59,7 +59,6 @@ public function tearDown(): void /** * testVerifyHappy - * */ public function testVerifyHappy() { @@ -87,7 +86,6 @@ public function testVerifyHappy() /** * testVerifyHappy - * */ public function testVerifyNotEnabled() { @@ -106,7 +104,6 @@ public function testVerifyNotEnabled() /** * testVerifyHappy - * */ public function testVerifyGetShowQR() { diff --git a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php index 9c75ef05b..9a3d8a6ad 100644 --- a/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php +++ b/tests/TestCase/Controller/Traits/PasswordManagementTraitTest.php @@ -411,7 +411,6 @@ public function testRequestPasswordEmptyReference() /** * @dataProvider ensureUserActiveForResetPasswordFeature - * * @return void */ public function testEnsureUserActiveForResetPasswordFeature($ensureActive) @@ -451,7 +450,6 @@ public function ensureUserActiveForResetPasswordFeature() /** * @dataProvider ensureOneTimePasswordAuthenticatorResets - * * @return void */ public function testRequestGoogleAuthTokenResetWithValidUser($userId, $entityId, $method, $msg) diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php index 1a302095d..055940d13 100644 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -15,10 +15,10 @@ use Cake\Datasource\Exception\InvalidPrimaryKeyException; use Cake\Datasource\Exception\RecordNotFoundException; -use CakeDC\Users\Controller\Traits\SimpleCrudTrait; /** * Class SimpleCrudTraitTest + * * @package CakeDC\Users\Test\TestCase\Controller\Traits */ class SimpleCrudTraitTest extends BaseTraitTest diff --git a/tests/TestCase/Controller/Traits/U2fTraitTest.php b/tests/TestCase/Controller/Traits/U2fTraitTest.php index 7d2229983..eee53e676 100644 --- a/tests/TestCase/Controller/Traits/U2fTraitTest.php +++ b/tests/TestCase/Controller/Traits/U2fTraitTest.php @@ -111,7 +111,6 @@ public function dataProviderU2User() * * @param array $userData session user data * @param mixed $redirect expetected redirect - * * @dataProvider dataProviderU2User * @return void */ @@ -163,7 +162,7 @@ public function testU2fRegisterOkay() ->setMethods(['getRegisterData']) ->getMock(); - $registerRequest = new RegisterRequest("sample chalange", "https://localhost"); + $registerRequest = new RegisterRequest('sample chalange', 'https://localhost'); $signs = [ ['fake' => new \stdClass()], ['fake2' => new \stdClass()], @@ -223,7 +222,6 @@ public function dataProviderU2fRegisterRedirect() * * @param array $userData session user data * @param mixed $redirect expetected redirect - * * @dataProvider dataProviderU2fRegisterRedirect * @return void */ @@ -285,7 +283,7 @@ public function testU2fRegisterFinishOkay() ->setMethods(['doRegister']) ->getMock(); - $registerRequest = new RegisterRequest("sample chalange", "https://localhost"); + $registerRequest = new RegisterRequest('sample chalange', 'https://localhost'); $registerRequest = json_decode(json_encode($registerRequest)); $signs = [ ['fake' => new \stdClass()], @@ -296,9 +294,9 @@ public function testU2fRegisterFinishOkay() 'fakeB' => 'fakevalueb', ])); $registration = new Registration(); - $registration->certificate = "user registration cert " . time(); + $registration->certificate = 'user registration cert ' . time(); $registration->counter = 1; - $registration->publicKey = "pub skska08u90234230990"; + $registration->publicKey = 'pub skska08u90234230990'; $registration->keyHandle = 'hahdofa02390423udu9ma0dumfá0dsufm2um9432uu903u923'; $this->Trait->getRequest()->expects($this->once()) @@ -355,9 +353,9 @@ public function testU2fRegisterFinishOkay() $this->assertEquals(json_encode($registration), json_encode($savedRegistration)); $registration = new Registration(); - $registration->certificate = "user registration cert " . time(); + $registration->certificate = 'user registration cert ' . time(); $registration->counter = 1; - $registration->publicKey = "pub skska08u90234230990"; + $registration->publicKey = 'pub skska08u90234230990'; $registration->keyHandle = 'hahdofa02390423udu9ma0dumfá0dsufm2um9432uu903u923'; } @@ -383,16 +381,16 @@ public function testU2fRegisterFinishException() ->setMethods(['doRegister']) ->getMock(); - $registerRequest = new RegisterRequest("sample chalange", "https://localhost"); + $registerRequest = new RegisterRequest('sample chalange', 'https://localhost'); $registerRequest = json_decode(json_encode($registerRequest)); $registerResponse = json_decode(json_encode([ 'fakeA' => 'fakevaluea', 'fakeB' => 'fakevalueb', ])); $registration = new Registration(); - $registration->certificate = "user registration cert " . time(); + $registration->certificate = 'user registration cert ' . time(); $registration->counter = 1; - $registration->publicKey = "pub skska08u90234230990"; + $registration->publicKey = 'pub skska08u90234230990'; $registration->keyHandle = 'hahdofa02390423udu9ma0dumfá0dsufm2um9432uu903u923'; $this->Trait->getRequest()->expects($this->once()) @@ -453,9 +451,9 @@ public function testU2fRegisterFinishException() $this->assertNull($savedRegistration); $registration = new Registration(); - $registration->certificate = "user registration cert " . time(); + $registration->certificate = 'user registration cert ' . time(); $registration->counter = 1; - $registration->publicKey = "pub skska08u90234230990"; + $registration->publicKey = 'pub skska08u90234230990'; $registration->keyHandle = 'hahdofa02390423udu9ma0dumfá0dsufm2um9432uu903u923'; } @@ -483,7 +481,6 @@ public function dataProviderU2fAuthenticateRedirectCustomUser() * * @param array $userData session user data * @param mixed $redirect expetected redirect - * * @dataProvider dataProviderU2fAuthenticateRedirectCustomUser * @return void */ diff --git a/tests/TestCase/Mailer/UsersMailerTest.php b/tests/TestCase/Mailer/UsersMailerTest.php index 8c05b4ea1..294c245e9 100644 --- a/tests/TestCase/Mailer/UsersMailerTest.php +++ b/tests/TestCase/Mailer/UsersMailerTest.php @@ -170,7 +170,6 @@ public function testResetPassword() * @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 = []) diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index de714d186..b09099ce1 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -213,7 +213,7 @@ public function testSuccessfullyAuthenticated() public function dataProviderSocialAuthenticationException() { $missingEmail = [ - new MissingEmailException("Missing email"), + new MissingEmailException('Missing email'), [ 'key' => 'flash', 'element' => 'Flash/error', @@ -224,7 +224,7 @@ public function dataProviderSocialAuthenticationException() true, ]; $unknown = [ - new UnexpectedValueException("User not active"), + new UnexpectedValueException('User not active'), [ 'key' => 'flash', 'element' => 'Flash/error', diff --git a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php index ea5b2fb2b..b98fa6dac 100644 --- a/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/AuthFinderBehaviorTest.php @@ -57,7 +57,6 @@ public function tearDown(): void /** * Test findActive method. - * */ public function testFindActive() { diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php index 0a4eba8ac..6654896d8 100644 --- a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php @@ -69,7 +69,6 @@ public function tearDown(): void * @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 @@ -160,7 +159,6 @@ public function providerFacebookLinkSocialAccount() * * @param array $data Test input data * @param string $userId User id to add social account - * * @author Marcelo Rocha * @return void * @dataProvider providerFacebookLinkSocialAccountErrorSaving @@ -256,7 +254,6 @@ public function providerFacebookLinkSocialAccountErrorSaving() * @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 diff --git a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php index 97268841b..23b12f02f 100644 --- a/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/PasswordBehaviorTest.php @@ -28,6 +28,7 @@ /** * Test Case + * * @property \CakeDC\Users\Model\Behavior\PasswordBehavior Behavior */ class PasswordBehaviorTest extends TestCase @@ -79,7 +80,6 @@ public function tearDown(): void /** * Test resetToken - * */ public function testResetToken() { @@ -99,7 +99,6 @@ public function testResetToken() /** * Test resetToken - * */ public function testResetTokenSendEmail() { diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index c3cfbd780..da7a640da 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -191,7 +191,6 @@ public function testValidateRegisterValidatorOption() /** * Test register method - * */ public function testValidateRegisterTosRequired() { diff --git a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php index decc19871..684f6c4db 100644 --- a/tests/TestCase/Model/Behavior/SocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/SocialBehaviorTest.php @@ -126,7 +126,6 @@ public function testSocialLoginFacebookProviderUsingEmail($data, $options, $data /** * Provider for socialLogin with facebook and not existing user - * */ public function providerFacebookSocialLogin() { @@ -255,7 +254,6 @@ public function testSocialLoginExistingReferenceOkay($data, $options) /** * Provider for socialLogin with facebook with existing and active user - * */ public function providerFacebookSocialLoginExistingReference() { @@ -296,7 +294,6 @@ public function testSocialLoginExistingNotActiveReference($data, $options) /** * Provider for socialLogin with existing and active user and not active social account - * */ public function providerSocialLoginExistingAndNotActiveAccount() { @@ -337,7 +334,6 @@ public function testSocialLoginExistingReferenceNotActiveUser($data, $options) /** * Provider for socialLogin with existing and active account but not active user - * */ public function providerSocialLoginExistingAccountNotActiveUser() { @@ -370,7 +366,6 @@ public function testSocialLoginNoEmail($data, $options) /** * Provider for socialLogin with facebook and not existing user - * */ public function providerFacebookSocialLoginNoEmail() { @@ -414,7 +409,6 @@ public function testGenerateUniqueUsername($param, $expected) /** * Provider for socialLogin with facebook and not existing user - * */ public function providerGenerateUsername() { diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 528be5977..7aa6b9d17 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -270,7 +270,6 @@ public function testSocialLoginCreateNewAccountWithNoCredentials() /** * Test socialLogin - * */ public function testSocialLoginCreateNewAccount() { diff --git a/tests/TestCase/Utility/UsersUrlTest.php b/tests/TestCase/Utility/UsersUrlTest.php index 2134a55ce..42db22eee 100644 --- a/tests/TestCase/Utility/UsersUrlTest.php +++ b/tests/TestCase/Utility/UsersUrlTest.php @@ -372,7 +372,6 @@ public function dataProviderCheckActionOnRequest() * @param array $params request params * @param string $controller users controller * @param bool $expected result expected - * * @dataProvider dataProviderCheckActionOnRequest * @return void */ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index e8575c540..212a3b467 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -29,7 +29,7 @@ return $root; } } while ($root !== $lastRoot); - throw new Exception("Cannot find the root of the application, unable to run tests"); + throw new Exception('Cannot find the root of the application, unable to run tests'); }; $root = $findRoot(__FILE__); unset($findRoot); diff --git a/tests/test_app/TestApp/Controller/AppController.php b/tests/test_app/TestApp/Controller/AppController.php index 947d6a0c4..db11ec36d 100644 --- a/tests/test_app/TestApp/Controller/AppController.php +++ b/tests/test_app/TestApp/Controller/AppController.php @@ -21,7 +21,6 @@ * * Add your application-wide methods in the class below, your controllers * will inherit them. - * */ class AppController extends Controller { diff --git a/tests/test_app/TestApp/Mailer/OverrideMailer.php b/tests/test_app/TestApp/Mailer/OverrideMailer.php index 792001a4f..3dbe44fe8 100644 --- a/tests/test_app/TestApp/Mailer/OverrideMailer.php +++ b/tests/test_app/TestApp/Mailer/OverrideMailer.php @@ -18,12 +18,12 @@ /** * Override default mailer class to test customization - * */ class OverrideMailer extends UsersMailer { /** * Override the resetPassword email with a custom template and subject + * * @param EntityInterface $user * @return array|void */ From 72e5498d4cb95aab784a360a6b064527fd2c3a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 8 Aug 2020 17:20:28 +0100 Subject: [PATCH 563/685] #fix-deprecations-tests fix stan --- src/Model/Behavior/RegisterBehavior.php | 9 +++++++++ src/View/Helper/AuthLinkHelper.php | 3 +++ 2 files changed, 12 insertions(+) diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index e73b46cc0..01bc06623 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -29,6 +29,15 @@ class RegisterBehavior extends BaseTokenBehavior { use MailerAwareTrait; + /** + * @var bool + */ + protected $validateEmail; + /** + * @var bool + */ + protected $useTos; + /** * Constructor hook method. * diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index ab4af59ac..b793e4a50 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -13,11 +13,14 @@ namespace CakeDC\Users\View\Helper; +use Cake\View\Helper\FormHelper; use Cake\View\Helper\HtmlHelper; use CakeDC\Auth\Traits\IsAuthorizedTrait; /** * AuthLink helper + * + * @property FormHelper $Form */ class AuthLinkHelper extends HtmlHelper { From 15a658e34470e18f037a11a4fc84bbfb1d6b34f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 8 Aug 2020 17:30:24 +0100 Subject: [PATCH 564/685] #fix-deprecations-tests fix cs --- src/View/Helper/AuthLinkHelper.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index b793e4a50..06274ae37 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -13,14 +13,13 @@ namespace CakeDC\Users\View\Helper; -use Cake\View\Helper\FormHelper; use Cake\View\Helper\HtmlHelper; use CakeDC\Auth\Traits\IsAuthorizedTrait; /** * AuthLink helper * - * @property FormHelper $Form + * @property \Cake\View\Helper\FormHelper $Form */ class AuthLinkHelper extends HtmlHelper { From 7c3257d53f5cd4d9da26bb4ebb33e67b7cb09aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 10 Aug 2020 11:19:46 +0100 Subject: [PATCH 565/685] #fix-deprecations-tests make stan happy --- phpstan.neon | 6 +++++- src/Controller/UsersController.php | 2 ++ src/View/Helper/AuthLinkHelper.php | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 0254599fe..f6dbf5f0b 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -5,8 +5,12 @@ parameters: level: 6 checkMissingIterableValueType: false checkGenericClassInNonGenericObjectType: false - autoload_files: + bootstrapFiles: - tests/bootstrap.php + excludes_analyse: + - src/Controller/SocialAccountsController.php + - src/Controller/UsersAccountsController.php + - src/Controller/AppAccountsController.php ignoreErrors: services: diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 741f06bf6..3130a6e81 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -13,6 +13,7 @@ namespace CakeDC\Users\Controller; +use Cake\Controller\Component\SecurityComponent; use CakeDC\Users\Controller\Traits\LinkSocialTrait; use CakeDC\Users\Controller\Traits\LoginTrait; use CakeDC\Users\Controller\Traits\OneTimePasswordVerifyTrait; @@ -27,6 +28,7 @@ * Users Controller * * @property \CakeDC\Users\Model\Table\UsersTable $Users + * @property SecurityComponent $Security */ class UsersController extends AppController { diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index 06274ae37..b793e4a50 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -13,13 +13,14 @@ namespace CakeDC\Users\View\Helper; +use Cake\View\Helper\FormHelper; use Cake\View\Helper\HtmlHelper; use CakeDC\Auth\Traits\IsAuthorizedTrait; /** * AuthLink helper * - * @property \Cake\View\Helper\FormHelper $Form + * @property FormHelper $Form */ class AuthLinkHelper extends HtmlHelper { From e14b7e5fb1053e4b9bc79b86c92814ad73eefa51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 11 Aug 2020 09:13:32 +0100 Subject: [PATCH 566/685] #fix-deprecations-tests cleanup baseline --- phpstan-baseline.neon | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index c670af94d..fcd00723e 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -37,21 +37,11 @@ parameters: count: 2 path: src\Controller\UsersController.php - - - message: "#^Parameter \\#1 \\$user of method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:onVerifyGetSecret\\(\\) expects CakeDC\\\\Users\\\\Model\\\\Entity\\\\User, array\\|string\\|null given\\.$#" - count: 1 - path: src\Controller\UsersController.php - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:\\$OneTimePasswordAuthenticator\\.$#" count: 3 path: src\Controller\UsersController.php - - - message: "#^Parameter \\#2 \\$user of method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:onPostVerifyCodeOkay\\(\\) expects CakeDC\\\\Users\\\\Model\\\\Entity\\\\User, array\\|string\\|null given\\.$#" - count: 1 - path: src\Controller\UsersController.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validationPasswordConfirm\\(\\)\\.$#" count: 1 @@ -182,16 +172,6 @@ parameters: count: 1 path: src\Model\Behavior\PasswordBehavior.php - - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Behavior\\\\RegisterBehavior\\:\\:\\$validateEmail\\.$#" - count: 4 - path: src\Model\Behavior\RegisterBehavior.php - - - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Behavior\\\\RegisterBehavior\\:\\:\\$useTos\\.$#" - count: 1 - path: src\Model\Behavior\RegisterBehavior.php - - message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$validated\\.$#" count: 1 @@ -292,22 +272,8 @@ parameters: count: 2 path: src\Shell\UsersShell.php - - - message: "#^Call to an undefined method CakeDC\\\\Users\\\\Model\\\\Table\\\\UsersTable\\:\\:resetToken\\(\\)\\.$#" - count: 1 - path: src\Shell\UsersShell.php - - - - message: "#^Call to an undefined method CakeDC\\\\Users\\\\Model\\\\Table\\\\UsersTable\\:\\:generateUniqueUsername\\(\\)\\.$#" - count: 1 - path: src\Shell\UsersShell.php - - message: "#^Parameter \\#1 \\$message of method Cake\\\\Controller\\\\Controller\\:\\:log\\(\\)\\ expects string, Exception given.$#" count: 1 path: src\Controller\Traits\OneTimePasswordVerifyTrait.php - - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\View\\\\Helper\\\\AuthLinkHelper\\:\\:\\$Form\\.$#" - count: 1 - path: src\View\Helper\AuthLinkHelper.php From 84b29918f4fa915f6c7cc3fb5ddf067f51ec9f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 11 Aug 2020 09:20:41 +0100 Subject: [PATCH 567/685] #fix-deprecations-tests fix baseline and errors --- phpstan-baseline.neon | 12 ------------ src/Controller/Traits/ReCaptchaTrait.php | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index fcd00723e..146e9ed85 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,5 +1,3 @@ - - parameters: ignoreErrors: - @@ -72,11 +70,6 @@ parameters: count: 1 path: src\Controller\UsersController.php - - - message: "#^Method CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:_getReCaptchaInstance\\(\\) should return ReCaptcha\\\\ReCaptcha but returns null\\.$#" - count: 1 - path: src\Controller\UsersController.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:register\\(\\)\\.$#" count: 2 @@ -97,11 +90,6 @@ parameters: count: 2 path: src\Controller\UsersController.php - - - message: "#^Method CakeDC\\\\Users\\\\Authenticator\\\\SocialPendingEmailAuthenticator\\:\\:_getReCaptchaInstance\\(\\) should return ReCaptcha\\\\ReCaptcha but returns null\\.$#" - count: 1 - path: src\Authenticator\SocialPendingEmailAuthenticator.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:socialLogin\\(\\)\\.$#" count: 1 diff --git a/src/Controller/Traits/ReCaptchaTrait.php b/src/Controller/Traits/ReCaptchaTrait.php index fb9ab7bcc..410511b6e 100644 --- a/src/Controller/Traits/ReCaptchaTrait.php +++ b/src/Controller/Traits/ReCaptchaTrait.php @@ -44,7 +44,7 @@ public function validateReCaptcha($recaptchaResponse, $clientIp) /** * Create reCaptcha instance if enabled in configuration * - * @return \ReCaptcha\ReCaptcha + * @return \ReCaptcha\ReCaptcha|null */ protected function _getReCaptchaInstance() { From 13df7986c7bbb9256873ed866cb9bac59be5436f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 11 Aug 2020 09:57:37 +0100 Subject: [PATCH 568/685] #fix-deprecations-tests fix cs --- src/Controller/UsersController.php | 3 +-- src/View/Helper/AuthLinkHelper.php | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 3130a6e81..6cffb4590 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -13,7 +13,6 @@ namespace CakeDC\Users\Controller; -use Cake\Controller\Component\SecurityComponent; use CakeDC\Users\Controller\Traits\LinkSocialTrait; use CakeDC\Users\Controller\Traits\LoginTrait; use CakeDC\Users\Controller\Traits\OneTimePasswordVerifyTrait; @@ -28,7 +27,7 @@ * Users Controller * * @property \CakeDC\Users\Model\Table\UsersTable $Users - * @property SecurityComponent $Security + * @property \Cake\Controller\Component\SecurityComponent $Security */ class UsersController extends AppController { diff --git a/src/View/Helper/AuthLinkHelper.php b/src/View/Helper/AuthLinkHelper.php index b793e4a50..06274ae37 100644 --- a/src/View/Helper/AuthLinkHelper.php +++ b/src/View/Helper/AuthLinkHelper.php @@ -13,14 +13,13 @@ namespace CakeDC\Users\View\Helper; -use Cake\View\Helper\FormHelper; use Cake\View\Helper\HtmlHelper; use CakeDC\Auth\Traits\IsAuthorizedTrait; /** * AuthLink helper * - * @property FormHelper $Form + * @property \Cake\View\Helper\FormHelper $Form */ class AuthLinkHelper extends HtmlHelper { From 170756ccba382a3f2f7a28a0820f310eebb0c04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Mon, 24 Aug 2020 17:29:37 +0100 Subject: [PATCH 569/685] Revert "Pick config/users.php file by default if exists #508" This reverts commit ef7fa221e94fcd9cdce66f01f2ff9b702e5a3c14. --- config/bootstrap.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/config/bootstrap.php b/config/bootstrap.php index 3e4b98678..d78acc8b7 100644 --- a/config/bootstrap.php +++ b/config/bootstrap.php @@ -15,10 +15,6 @@ use Cake\Routing\Router; Configure::load('CakeDC/Users.users'); -if (file_exists(CONFIG . 'users.php')) { - Configure::load('users'); -} - collection((array)Configure::read('Users.config'))->each(function ($file) { Configure::load($file); }); From ad0ac38c6e356333c585eac5acc44ea611642a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 16 Oct 2020 09:08:40 +0100 Subject: [PATCH 570/685] Update Configuration.md Add example for password hasher customization --- Docs/Documentation/Configuration.md | 34 +++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 121127cb3..4ecf55d3e 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -210,3 +210,37 @@ Check https://book.cakephp.org/4/en/core-libraries/internationalization-and-loca 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. + +Password Hasher customization +----------------------------- + +Override the `Auth.Identifiers.Password` key in configuration adding a `passwordHasher` key https://book.cakephp.org/authentication/2/en/password-hashers.html#upgrading-hashing-algorithms + +For example: + +```php + 'Auth.Identifiers' => [ + 'Password' => [ + 'className' => 'Authentication.Password', + 'fields' => [ + 'username' => ['username', 'email'], + 'password' => 'password', + ], + 'resolver' => [ + 'className' => 'Authentication.Orm', + 'finder' => 'active', + ], + 'passwordHasher' => [ + 'className' => 'Authentication.Fallback', + 'hashers' => [ + 'Authentication.Default', + [ + 'className' => 'Authentication.Legacy', + 'hashType' => 'md5', + 'salt' => false, // turn off default usage of salt + ], + ], + ], + ], + ], +``` From f949b5ac96b5ab74cd9e5bb737b10bd8faca6c6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 16 Oct 2020 09:11:02 +0100 Subject: [PATCH 571/685] Update Configuration.md Fix docs for using emai --- Docs/Documentation/Configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 4ecf55d3e..b1a6d352e 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -165,7 +165,7 @@ You need to configure 2 things: ```php $identifiers = Configure::read('Auth.Identifiers'); - $identifiers['Authentication.Password']['fields']['username'] = 'email'; + $identifiers['Password']['fields']['username'] = 'email'; Configure::write('Auth.Identifiers', $identifiers); ``` From 647eb861da1211136bc14c66a2a92c9186c31703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Fri, 16 Oct 2020 11:00:44 +0100 Subject: [PATCH 572/685] prepare release --- .semver | 2 +- CHANGELOG.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.semver b/.semver index caf33d9cb..1f812fd69 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 9 :minor: 0 -:patch: 3 +:patch: 4 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index 30ee96d6e..baeeb5ce2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ Releases for CakePHP 4 * Next * +* 9.0.4 + * Fixed deprecations and stan issues + * Improved docs + * Fixed issue where RememberMe cookie + * Fixed deprecated UserHelper::isAuthorized + * 9.0.3 * Ukrainian (uk) by @yarkm13 * Docs improvements From 1776bead316027316aaaaca7a321dfd576d51576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Fri, 16 Oct 2020 16:55:21 +0200 Subject: [PATCH 573/685] Remove outdated statement --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d230e53be..459fdaf7b 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,8 @@ Versions and branches | 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! +The **Users** plugin covers the following features: -It covers the following features: * User registration * Login/logout * Social login (Facebook, Twitter, Instagram, Google, Linkedin, etc) @@ -36,6 +35,7 @@ It covers the following features: * One-Time Password for Two-Factor Authentication 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 From a81affc0abb5d60950e182f782a2e858e06e0225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Fri, 16 Oct 2020 17:19:07 +0200 Subject: [PATCH 574/685] Update version & branches map - Move developmen up - Correct statement about CakePHP version behind develop branch - Reformat table - Update latest versions of each branch --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 459fdaf7b..00694d77c 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,17 @@ CakeDC Users Plugin Versions and branches --------------------- -| CakePHP | CakeDC Users Plugin | Tag | Notes | -| :-------------: | :------------------------: | :--: | :---- | -| ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.3 | stable | -| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.3 | stable | -| ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | -| ^3.7 <4.0 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | -| 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | -| 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | -| 3.4 | [5.x](https://github.com/cakedc/users/tree/5.x) | 5.2.0 | stable | -| 3.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 | +| CakePHP | CakeDC Users Plugin Branch | Tag | Notes | +| :-------------: | :------------------------------------------------------: | :--: | :---- | +| ^4.0 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | +| ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.4 | stable | +| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.4 | stable | +| ^3.7 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | +| 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | +| 3.5 | [6.x](https://github.com/cakedc/users/tree/6.x) | 6.0.1 | stable | +| 3.4 | [5.x](https://github.com/cakedc/users/tree/5.x) | 5.2.0 | stable | +| >=3.2.9 <3.4.0 | [4.x](https://github.com/cakedc/users/tree/4.x) | 4.2.1 | stable | +| ^2.10 | [2.x](https://github.com/cakedc/users/tree/2.x) | 2.2.0 |stable | The **Users** plugin covers the following features: From 1e2385f33a73be94806b7176875247537333682d Mon Sep 17 00:00:00 2001 From: Curtis Gibby Date: Sat, 24 Oct 2020 14:18:01 -0600 Subject: [PATCH 575/685] Add PHP syntax highlighting --- Docs/Documentation/InterceptLoginAction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/InterceptLoginAction.md b/Docs/Documentation/InterceptLoginAction.md index a4bc96336..2e27b868d 100644 --- a/Docs/Documentation/InterceptLoginAction.md +++ b/Docs/Documentation/InterceptLoginAction.md @@ -6,7 +6,7 @@ some specific login, like redirect user to another url or set user data. A simple way to intercept the login action is by creating a custom middleware, the following example shows how to set user data and redirect to anothe url. -``` +```php Date: Sat, 24 Oct 2020 14:22:26 -0600 Subject: [PATCH 576/685] Use PHP syntax highlighting. --- Docs/Documentation/SocialAuthentication.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Docs/Documentation/SocialAuthentication.md b/Docs/Documentation/SocialAuthentication.md index 7ec4211f2..27223000e 100644 --- a/Docs/Documentation/SocialAuthentication.md +++ b/Docs/Documentation/SocialAuthentication.md @@ -20,7 +20,7 @@ Setup Create the Facebook/Twitter applications you want to use and setup the configuration like this: Config/bootstrap.php -``` +```php Configure::write('OAuth.providers.facebook.options.clientId', 'YOUR APP ID'); Configure::write('OAuth.providers.facebook.options.clientSecret', 'YOUR APP SECRET'); @@ -30,7 +30,7 @@ Configure::write('OAuth.providers.twitter.options.clientSecret', 'YOUR APP SECRE You can also change the default settings for social authenticate: -``` +```php Configure::write('Users', [ 'Email' => [ //determines if the user should include email @@ -65,7 +65,7 @@ In most situations you would not need to change any Oauth setting besides applic For new facebook aps you must use the graphApiVersion 2.8 or greater: -``` +```php Configure::write('OAuth.providers.facebook.options.graphApiVersion', 'v2.8'); ``` @@ -75,7 +75,7 @@ User Helper You can use the helper included with the plugin to create Facebook/Twitter buttons: In templates -``` +```php $this->User->facebookLogin(); $this->User->twitterLogin(); @@ -124,7 +124,7 @@ The social identifier "CakeDC/Users.Social", works with data provider by both so it is responsible of finding or creating a user registry for the social user data request. By default it'll fetch user data with finder 'all', but you can use a custom one. Add this to your Application class, after CakeDC/Users Plugin is loaded. -``` +```php $identifiers = Configure::read('Auth.Identifiers'); $identifiers['CakeDC/Users.Social']['authFinder'] = 'customSocialAuth'; Configure::write('Auth.Identifiers', $identifiers); @@ -139,12 +139,12 @@ There are two custom messages (Auth.SocialLoginFailure.messages) and one default To use a custom component to handle the login, do: -``` +```php Configure::write('Auth.SocialLoginFailure.component', 'MyLoginA'); ``` The default configuration is: -``` +```php [ ... 'Auth' => [ From d2f3737754861cca8f23a948c3887872d1bc6a69 Mon Sep 17 00:00:00 2001 From: Johannes Nohl Date: Sun, 1 Nov 2020 23:20:55 +0100 Subject: [PATCH 577/685] Make clear how using the user's email to login work As mentioned in https://github.com/CakeDC/users/issues/912#issuecomment-720160238. --- Docs/Documentation/Configuration.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index b1a6d352e..dea40fd4d 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -159,14 +159,23 @@ To learn more about it please check the configurations for [Authentication](Auth ## Using the user's email to login -You need to configure 2 things: +You need to configure 2 things (version 9.0.4): -* Change the Password identifier fields configuration to let it use the email instead of the username for user identify. Add this to your Application class, after CakeDC/Users Plugin is loaded. +* Change the Password identifier fields and the Authenticator for Forms configuration to let it use the email instead of the username for user identify. Add this to your Application class, right before CakeDC/Users Plugin is loaded. ```php - $identifiers = Configure::read('Auth.Identifiers'); - $identifiers['Password']['fields']['username'] = 'email'; - Configure::write('Auth.Identifiers', $identifiers); + // Load more plugins here + $identifiers = Configure::read('Auth.Identifiers'); + $identifiers['Password']['fields']['username'] = 'email'; + Configure::write('Auth.Identifiers', $identifiers); + + $authenticators = Configure::read('Auth.Authenticators'); + $authenticators['Form']['fields']['username'] = 'email'; + Configure::write('Auth.Authenticators', $authenticators); + + //Configure::write('Users.config', ['users', 'permissions']); + + $this->addPlugin(\CakeDC\Users\Plugin::class); ``` * Override the login.php template to change the Form->control to "email". From 2af8a207690b331fc4ad2c70c1db46a213574f14 Mon Sep 17 00:00:00 2001 From: Eugene Ritter Date: Tue, 10 Nov 2020 16:41:00 -0600 Subject: [PATCH 578/685] Created 2 objects to replace functions that were on the Plugin class: AuthorizationServiceProvider and AuthenticationServiceProvider. Both of these class implement the respective interfaces previously on the Plugin class. Both classes are now passed MiddlewareQueueLoader and type hints that were to the concretion "Plugin" are now the abstraction interfaces. --- src/Loader/MiddlewareQueueLoader.php | 42 ++- src/Plugin.php | 72 +---- .../AuthenticationServiceProvider.php | 39 +++ src/Provider/AuthorizationServiceProvider.php | 39 +++ src/Provider/ServiceProviderLoaderTrait.php | 56 ++++ tests/TestCase/PluginTest.php | 245 ----------------- .../AuthenticationServiceProviderTest.php | 249 ++++++++++++++++++ .../AuthorizationServiceProviderTest.php | 63 +++++ 8 files changed, 485 insertions(+), 320 deletions(-) create mode 100644 src/Provider/AuthenticationServiceProvider.php create mode 100644 src/Provider/AuthorizationServiceProvider.php create mode 100644 src/Provider/ServiceProviderLoaderTrait.php create mode 100644 tests/TestCase/Provider/AuthenticationServiceProviderTest.php create mode 100644 tests/TestCase/Provider/AuthorizationServiceProviderTest.php diff --git a/src/Loader/MiddlewareQueueLoader.php b/src/Loader/MiddlewareQueueLoader.php index 6b943870a..cb140d87c 100644 --- a/src/Loader/MiddlewareQueueLoader.php +++ b/src/Loader/MiddlewareQueueLoader.php @@ -13,7 +13,9 @@ namespace CakeDC\Users\Loader; +use Authentication\AuthenticationServiceProviderInterface; use Authentication\Middleware\AuthenticationMiddleware; +use Authorization\AuthorizationServiceProviderInterface; use Authorization\Middleware\AuthorizationMiddleware; use Authorization\Middleware\RequestAuthorizationMiddleware; use Cake\Core\Configure; @@ -21,7 +23,6 @@ use CakeDC\Auth\Middleware\TwoFactorMiddleware; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; -use CakeDC\Users\Plugin; /** * Class MiddlewareQueueLoader @@ -40,16 +41,20 @@ class MiddlewareQueueLoader * For 'Auth.Authorization.loadRbacMiddleware' load RbacMiddleware * * @param \Cake\Http\MiddlewareQueue $middlewareQueue The middleware queue to update. - * @param \CakeDC\Users\Plugin $plugin Users plugin object + * @param \Authentication\AuthenticationServiceProviderInterface $authenticationServiceProvider Loads the auth service + * @param \Authorization\AuthorizationServiceProviderInterface $authorizationServiceProvider Loads the authorization service * @return \Cake\Http\MiddlewareQueue */ - public function __invoke(MiddlewareQueue $middlewareQueue, Plugin $plugin) - { + public function __invoke( + MiddlewareQueue $middlewareQueue, + AuthenticationServiceProviderInterface $authenticationServiceProvider, + AuthorizationServiceProviderInterface $authorizationServiceProvider + ) { $this->loadSocialMiddleware($middlewareQueue); - $this->loadAuthenticationMiddleware($middlewareQueue, $plugin); + $this->loadAuthenticationMiddleware($middlewareQueue, $authenticationServiceProvider); $this->load2faMiddleware($middlewareQueue); - return $this->loadAuthorizationMiddleware($middlewareQueue, $plugin); + return $this->loadAuthorizationMiddleware($middlewareQueue, $authorizationServiceProvider); } /** @@ -71,12 +76,14 @@ protected function loadSocialMiddleware(MiddlewareQueue $middlewareQueue) * Load authentication middleware * * @param \Cake\Http\MiddlewareQueue $middlewareQueue queue of middleware - * @param \CakeDC\Users\Plugin $plugin Users plugin object + * @param \Authentication\AuthenticationServiceProviderInterface $authenticationServiceProvider Authentication service provider * @return void */ - protected function loadAuthenticationMiddleware(MiddlewareQueue $middlewareQueue, Plugin $plugin) - { - $authentication = new AuthenticationMiddleware($plugin); + protected function loadAuthenticationMiddleware( + MiddlewareQueue $middlewareQueue, + AuthenticationServiceProviderInterface $authenticationServiceProvider + ) { + $authentication = new AuthenticationMiddleware($authenticationServiceProvider); $middlewareQueue->add($authentication); } @@ -100,15 +107,22 @@ protected function load2faMiddleware(MiddlewareQueue $middlewareQueue) * Load authorization middleware based on Auth.Authorization. * * @param \Cake\Http\MiddlewareQueue $middlewareQueue queue of middleware - * @param \CakeDC\Users\Plugin $plugin Users plugin object + * @param \Authorization\AuthorizationServiceProviderInterface $authorizationServiceProvider Authorization service provider * @return \Cake\Http\MiddlewareQueue */ - protected function loadAuthorizationMiddleware(MiddlewareQueue $middlewareQueue, Plugin $plugin) - { + protected function loadAuthorizationMiddleware( + MiddlewareQueue $middlewareQueue, + AuthorizationServiceProviderInterface $authorizationServiceProvider + ) { if (Configure::read('Auth.Authorization.enable') === false) { return $middlewareQueue; } - $middlewareQueue->add(new AuthorizationMiddleware($plugin, Configure::read('Auth.AuthorizationMiddleware'))); + $middlewareQueue->add( + new AuthorizationMiddleware( + $authorizationServiceProvider, + Configure::read('Auth.AuthorizationMiddleware') + ) + ); if (Configure::read('Auth.AuthorizationMiddleware.requireAuthorizationCheck') !== false) { $middlewareQueue->add(new RequestAuthorizationMiddleware()); } diff --git a/src/Plugin.php b/src/Plugin.php index 8ad5ba6fd..4981d736f 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -13,17 +13,16 @@ namespace CakeDC\Users; -use Authentication\AuthenticationServiceInterface; -use Authentication\AuthenticationServiceProviderInterface; -use Authorization\AuthorizationServiceInterface; -use Authorization\AuthorizationServiceProviderInterface; use Cake\Core\BasePlugin; -use Cake\Core\Configure; use Cake\Http\MiddlewareQueue; -use Psr\Http\Message\ServerRequestInterface; +use CakeDC\Users\Provider\AuthenticationServiceProvider; +use CakeDC\Users\Provider\AuthorizationServiceProvider; +use CakeDC\Users\Provider\ServiceProviderLoaderTrait; -class Plugin extends BasePlugin implements AuthenticationServiceProviderInterface, AuthorizationServiceProviderInterface +class Plugin extends BasePlugin { + use ServiceProviderLoaderTrait; + /** * Plugin name. * @@ -43,29 +42,6 @@ class Plugin extends BasePlugin implements AuthenticationServiceProviderInterfac public const EVENT_ON_EXPIRED_TOKEN = 'Users.Global.onExpiredToken'; public const EVENT_AFTER_RESEND_TOKEN_VALIDATION = 'Users.Global.afterResendTokenValidation'; - /** - * Returns an authentication service instance. - * - * @param \Psr\Http\Message\ServerRequestInterface $request Request - * @return \Authentication\AuthenticationServiceInterface - */ - public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface - { - $key = 'Auth.Authentication.serviceLoader'; - - return $this->loadService($request, $key); - } - - /** - * @inheritDoc - */ - public function getAuthorizationService(ServerRequestInterface $request): AuthorizationServiceInterface - { - $key = 'Auth.Authorization.serviceLoader'; - - return $this->loadService($request, $key); - } - /** * @inheritDoc */ @@ -73,36 +49,10 @@ public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue { $loader = $this->getLoader('Users.middlewareQueueLoader'); - return $loader($middlewareQueue, $this); - } - - /** - * Load a service defined in configuration $loaderKey - * - * @param \Psr\Http\Message\ServerRequestInterface $request The request. - * @param string $loaderKey service loader key - * @return mixed - */ - protected function loadService(ServerRequestInterface $request, $loaderKey) - { - $serviceLoader = $this->getLoader($loaderKey); - - return $serviceLoader($request); - } - - /** - * Get the loader callable - * - * @param string $loaderKey loader configuration key - * @return callable - */ - protected function getLoader($loaderKey) - { - $serviceLoader = Configure::read($loaderKey); - if (is_string($serviceLoader)) { - $serviceLoader = new $serviceLoader(); - } - - return $serviceLoader; + return $loader( + $middlewareQueue, + new AuthenticationServiceProvider(), + new AuthorizationServiceProvider() + ); } } diff --git a/src/Provider/AuthenticationServiceProvider.php b/src/Provider/AuthenticationServiceProvider.php new file mode 100644 index 000000000..1c4dcc3e4 --- /dev/null +++ b/src/Provider/AuthenticationServiceProvider.php @@ -0,0 +1,39 @@ +loadService($request, $key); + } +} diff --git a/src/Provider/AuthorizationServiceProvider.php b/src/Provider/AuthorizationServiceProvider.php new file mode 100644 index 000000000..8c727f41a --- /dev/null +++ b/src/Provider/AuthorizationServiceProvider.php @@ -0,0 +1,39 @@ +loadService($request, $key); + } +} diff --git a/src/Provider/ServiceProviderLoaderTrait.php b/src/Provider/ServiceProviderLoaderTrait.php new file mode 100644 index 000000000..770826647 --- /dev/null +++ b/src/Provider/ServiceProviderLoaderTrait.php @@ -0,0 +1,56 @@ +getLoader($loaderKey); + + return $serviceLoader($request); + } + + /** + * Get the loader callable + * + * @param string $loaderKey loader configuration key + * @return callable + */ + protected function getLoader($loaderKey) + { + $serviceLoader = Configure::read($loaderKey); + if (is_string($serviceLoader)) { + $serviceLoader = new $serviceLoader(); + } + + return $serviceLoader; + } +} diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index befaaa762..24b4754ac 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -211,251 +211,6 @@ public function testMiddlewareNotGoogleAuthenticationAndNotSocial() $this->assertInstanceOf(RequestAuthorizationMiddleware::class, $middleware->current()); } - /** - * testGetAuthenticationService - * - * @return void - */ - public function testGetAuthenticationServiceCallableDefined() - { - $request = ServerRequestFactory::fromGlobals(); - $request->withQueryParams(['method' => __METHOD__]); - $service = new CakeDCAuthenticationService([ - 'identifiers' => [ - 'Authentication.Password', - ], - ]); - Configure::write('Auth.Authentication.serviceLoader', function ($aRequest) use ($request, $service) { - $this->assertSame($request, $aRequest); - - return $service; - }); - - $plugin = new Plugin(); - $actualService = $plugin->getAuthenticationService($request); - $this->assertSame($service, $actualService); - } - - /** - * testGetAuthenticationService - * - * @return void - */ - public function testGetAuthenticationService() - { - Configure::write('Auth.Authenticators', [ - 'Session' => [ - 'className' => 'Authentication.Session', - 'skipTwoFactorVerify' => true, - 'sessionKey' => 'CustomAuth', - 'fields' => ['username' => 'email'], - 'identify' => true, - ], - 'Form' => [ - 'className' => 'CakeDC/Auth.Form', - 'loginUrl' => '/login', - 'fields' => ['username' => 'email', 'password' => 'alt_password'], - ], - 'Token' => [ - 'className' => 'Authentication.Token', - 'skipTwoFactorVerify' => true, - 'header' => null, - 'queryParam' => 'api_key', - 'tokenPrefix' => null, - ], - ]); - Configure::write('Auth.Identifiers', [ - 'Password' => [ - 'className' => 'Authentication.Password', - 'fields' => [ - 'username' => 'email_2', - 'password' => 'password_2', - ], - ], - 'Token' => [ - 'className' => 'Authentication.Token', - 'tokenField' => 'api_token', - ], - 'Authentication.JwtSubject', - ]); - Configure::write('OneTimePasswordAuthenticator.login', true); - - $plugin = new Plugin(); - $service = $plugin->getAuthenticationService(new ServerRequest(), new Response()); - $this->assertInstanceOf(CakeDCAuthenticationService::class, $service); - - /** - * @var \Authentication\Authenticator\AuthenticatorCollection $authenticators - */ - $authenticators = $service->authenticators(); - $expected = [ - SessionAuthenticator::class => [ - 'fields' => ['username' => 'email'], - 'sessionKey' => 'CustomAuth', - 'identify' => true, - 'identityAttribute' => 'identity', - 'skipTwoFactorVerify' => true, - ], - FormAuthenticator::class => [ - 'loginUrl' => '/login', - 'keyCheckEnabledRecaptcha' => 'Users.reCaptcha.login', - 'fields' => ['username' => 'email', 'password' => 'alt_password'], - ], - TokenAuthenticator::class => [ - 'header' => null, - 'queryParam' => 'api_key', - 'tokenPrefix' => null, - 'skipTwoFactorVerify' => true, - ], - TwoFactorAuthenticator::class => [ - 'loginUrl' => null, - 'urlChecker' => 'Authentication.Default', - 'skipTwoFactorVerify' => true, - ], - ]; - $actual = []; - foreach ($authenticators as $key => $value) { - $actual[get_class($value)] = $value->getConfig(); - } - $this->assertEquals($expected, $actual); - - /** - * @var \Authentication\Identifier\IdentifierCollection $identifiers - */ - $identifiers = $service->identifiers(); - $expected = [ - PasswordIdentifier::class => [ - 'fields' => [ - 'username' => 'email_2', - 'password' => 'password_2', - ], - 'resolver' => 'Authentication.Orm', - 'passwordHasher' => null, - ], - TokenIdentifier::class => [ - 'tokenField' => 'api_token', - 'dataField' => 'token', - 'resolver' => 'Authentication.Orm', - ], - JwtSubjectIdentifier::class => [ - 'tokenField' => 'id', - 'dataField' => 'sub', - 'resolver' => 'Authentication.Orm', - ], - ]; - $actual = []; - foreach ($identifiers as $key => $value) { - $actual[get_class($value)] = $value->getConfig(); - } - $this->assertEquals($expected, $actual); - } - - /** - * testGetAuthenticationService - * - * @return void - */ - public function testGetAuthenticationServiceWithouOneTimePasswordAuthenticator() - { - Configure::write('Auth.Authenticators', [ - 'Session' => [ - 'className' => 'Authentication.Session', - 'skipTwoFactorVerify' => true, - 'sessionKey' => 'CustomAuth', - 'fields' => ['username' => 'email'], - 'identify' => true, - ], - 'Form' => [ - 'className' => 'CakeDC/Auth.Form', - 'loginUrl' => '/login', - 'fields' => ['username' => 'email', 'password' => 'alt_password'], - ], - 'Token' => [ - 'className' => 'Authentication.Token', - 'skipTwoFactorVerify' => true, - 'header' => null, - 'queryParam' => 'api_key', - 'tokenPrefix' => null, - ], - ]); - Configure::write('Auth.Identifiers', [ - 'Authentication.Password', - 'Token' => [ - 'className' => 'Authentication.Token', - 'tokenField' => 'api_token', - ], - 'Authentication.JwtSubject', - ]); - Configure::write('OneTimePasswordAuthenticator.login', false); - - $plugin = new Plugin(); - $service = $plugin->getAuthenticationService(new ServerRequest(), new Response()); - $this->assertInstanceOf(CakeDCAuthenticationService::class, $service); - - /** - * @var \Authentication\Authenticator\AuthenticatorCollection $authenticators - */ - $authenticators = $service->authenticators(); - $expected = [ - SessionAuthenticator::class => [ - 'fields' => ['username' => 'email'], - 'sessionKey' => 'CustomAuth', - 'identify' => true, - 'identityAttribute' => 'identity', - 'skipTwoFactorVerify' => true, - ], - FormAuthenticator::class => [ - 'loginUrl' => '/login', - 'fields' => ['username' => 'email', 'password' => 'alt_password'], - 'keyCheckEnabledRecaptcha' => 'Users.reCaptcha.login', - ], - TokenAuthenticator::class => [ - 'header' => null, - 'queryParam' => 'api_key', - 'tokenPrefix' => null, - 'skipTwoFactorVerify' => true, - ], - ]; - $actual = []; - foreach ($authenticators as $key => $value) { - $actual[get_class($value)] = $value->getConfig(); - } - $this->assertEquals($expected, $actual); - } - - /** - * testGetAuthorizationService - * - * @return void - */ - public function testGetAuthorizationService() - { - $plugin = new Plugin(); - $service = $plugin->getAuthorizationService(new ServerRequest()); - $this->assertInstanceOf(AuthorizationService::class, $service); - } - - /** - * testGetAuthorizationService - * - * @return void - */ - public function testGetAuthorizationServiceCallableDefined() - { - $request = ServerRequestFactory::fromGlobals(); - $request->withQueryParams(['method' => __METHOD__]); - $service = new AuthorizationService(new ResolverCollection()); - Configure::write('Auth.Authorization.serviceLoader', function ($aRequest) use ($request, $service) { - $this->assertSame($request, $aRequest); - - return $service; - }); - - $plugin = new Plugin(); - $actualService = $plugin->getAuthorizationService($request); - $this->assertSame($service, $actualService); - } - /** * test bootstrap method * diff --git a/tests/TestCase/Provider/AuthenticationServiceProviderTest.php b/tests/TestCase/Provider/AuthenticationServiceProviderTest.php new file mode 100644 index 000000000..710402173 --- /dev/null +++ b/tests/TestCase/Provider/AuthenticationServiceProviderTest.php @@ -0,0 +1,249 @@ + [ + 'className' => 'Authentication.Session', + 'skipTwoFactorVerify' => true, + 'sessionKey' => 'CustomAuth', + 'fields' => ['username' => 'email'], + 'identify' => true, + ], + 'Form' => [ + 'className' => 'CakeDC/Auth.Form', + 'loginUrl' => '/login', + 'fields' => ['username' => 'email', 'password' => 'alt_password'], + ], + 'Token' => [ + 'className' => 'Authentication.Token', + 'skipTwoFactorVerify' => true, + 'header' => null, + 'queryParam' => 'api_key', + 'tokenPrefix' => null, + ], + ]); + Configure::write('Auth.Identifiers', [ + 'Password' => [ + 'className' => 'Authentication.Password', + 'fields' => [ + 'username' => 'email_2', + 'password' => 'password_2', + ], + ], + 'Token' => [ + 'className' => 'Authentication.Token', + 'tokenField' => 'api_token', + ], + 'Authentication.JwtSubject', + ]); + Configure::write('OneTimePasswordAuthenticator.login', true); + + $authenticationServiceProvider = new AuthenticationServiceProvider(); + $service = $authenticationServiceProvider->getAuthenticationService(new ServerRequest(), new Response()); + $this->assertInstanceOf(CakeDCAuthenticationService::class, $service); + + /** + * @var \Authentication\Authenticator\AuthenticatorCollection $authenticators + */ + $authenticators = $service->authenticators(); + $expected = [ + SessionAuthenticator::class => [ + 'fields' => ['username' => 'email'], + 'sessionKey' => 'CustomAuth', + 'identify' => true, + 'identityAttribute' => 'identity', + 'skipTwoFactorVerify' => true, + ], + FormAuthenticator::class => [ + 'loginUrl' => '/login', + 'keyCheckEnabledRecaptcha' => 'Users.reCaptcha.login', + 'fields' => ['username' => 'email', 'password' => 'alt_password'], + ], + TokenAuthenticator::class => [ + 'header' => null, + 'queryParam' => 'api_key', + 'tokenPrefix' => null, + 'skipTwoFactorVerify' => true, + ], + TwoFactorAuthenticator::class => [ + 'loginUrl' => null, + 'urlChecker' => 'Authentication.Default', + 'skipTwoFactorVerify' => true, + ], + ]; + $actual = []; + foreach ($authenticators as $key => $value) { + $actual[get_class($value)] = $value->getConfig(); + } + $this->assertEquals($expected, $actual); + + /** + * @var \Authentication\Identifier\IdentifierCollection $identifiers + */ + $identifiers = $service->identifiers(); + $expected = [ + PasswordIdentifier::class => [ + 'fields' => [ + 'username' => 'email_2', + 'password' => 'password_2', + ], + 'resolver' => 'Authentication.Orm', + 'passwordHasher' => null, + ], + TokenIdentifier::class => [ + 'tokenField' => 'api_token', + 'dataField' => 'token', + 'resolver' => 'Authentication.Orm', + ], + JwtSubjectIdentifier::class => [ + 'tokenField' => 'id', + 'dataField' => 'sub', + 'resolver' => 'Authentication.Orm', + ], + ]; + $actual = []; + foreach ($identifiers as $key => $value) { + $actual[get_class($value)] = $value->getConfig(); + } + $this->assertEquals($expected, $actual); + } + + /** + * testGetAuthenticationService + * + * @return void + */ + public function testGetAuthenticationServiceCallableDefined() + { + $request = ServerRequestFactory::fromGlobals(); + $request->withQueryParams(['method' => __METHOD__]); + $service = new CakeDCAuthenticationService([ + 'identifiers' => [ + 'Authentication.Password', + ], + ]); + Configure::write('Auth.Authentication.serviceLoader', function ($aRequest) use ($request, $service) { + $this->assertSame($request, $aRequest); + + return $service; + }); + + $authenticationServiceProvider = new AuthenticationServiceProvider(); + $actualService = $authenticationServiceProvider->getAuthenticationService($request); + $this->assertSame($service, $actualService); + } + + /** + * testGetAuthenticationService + * + * @return void + */ + public function testGetAuthenticationServiceWithoutOneTimePasswordAuthenticator() + { + Configure::write('Auth.Authenticators', [ + 'Session' => [ + 'className' => 'Authentication.Session', + 'skipTwoFactorVerify' => true, + 'sessionKey' => 'CustomAuth', + 'fields' => ['username' => 'email'], + 'identify' => true, + ], + 'Form' => [ + 'className' => 'CakeDC/Auth.Form', + 'loginUrl' => '/login', + 'fields' => ['username' => 'email', 'password' => 'alt_password'], + ], + 'Token' => [ + 'className' => 'Authentication.Token', + 'skipTwoFactorVerify' => true, + 'header' => null, + 'queryParam' => 'api_key', + 'tokenPrefix' => null, + ], + ]); + Configure::write('Auth.Identifiers', [ + 'Authentication.Password', + 'Token' => [ + 'className' => 'Authentication.Token', + 'tokenField' => 'api_token', + ], + 'Authentication.JwtSubject', + ]); + Configure::write('OneTimePasswordAuthenticator.login', false); + + $authenticationServiceProvider = new AuthenticationServiceProvider(); + $service = $authenticationServiceProvider->getAuthenticationService(new ServerRequest(), new Response()); + $this->assertInstanceOf(CakeDCAuthenticationService::class, $service); + + /** + * @var \Authentication\Authenticator\AuthenticatorCollection $authenticators + */ + $authenticators = $service->authenticators(); + $expected = [ + SessionAuthenticator::class => [ + 'fields' => ['username' => 'email'], + 'sessionKey' => 'CustomAuth', + 'identify' => true, + 'identityAttribute' => 'identity', + 'skipTwoFactorVerify' => true, + ], + FormAuthenticator::class => [ + 'loginUrl' => '/login', + 'fields' => ['username' => 'email', 'password' => 'alt_password'], + 'keyCheckEnabledRecaptcha' => 'Users.reCaptcha.login', + ], + TokenAuthenticator::class => [ + 'header' => null, + 'queryParam' => 'api_key', + 'tokenPrefix' => null, + 'skipTwoFactorVerify' => true, + ], + ]; + $actual = []; + foreach ($authenticators as $key => $value) { + $actual[get_class($value)] = $value->getConfig(); + } + $this->assertEquals($expected, $actual); + } +} diff --git a/tests/TestCase/Provider/AuthorizationServiceProviderTest.php b/tests/TestCase/Provider/AuthorizationServiceProviderTest.php new file mode 100644 index 000000000..d8ffb30e5 --- /dev/null +++ b/tests/TestCase/Provider/AuthorizationServiceProviderTest.php @@ -0,0 +1,63 @@ +getAuthorizationService(new ServerRequest()); + $this->assertInstanceOf(AuthorizationService::class, $service); + } + + /** + * testGetAuthorizationService + * + * @return void + */ + public function testGetAuthorizationServiceCallableDefined() + { + $request = ServerRequestFactory::fromGlobals(); + $request->withQueryParams(['method' => __METHOD__]); + $service = new AuthorizationService(new ResolverCollection()); + Configure::write('Auth.Authorization.serviceLoader', function ($aRequest) use ($request, $service) { + $this->assertSame($request, $aRequest); + + return $service; + }); + + $authorizationServiceProvider = new AuthorizationServiceProvider(); + $actualService = $authorizationServiceProvider->getAuthorizationService($request); + $this->assertSame($service, $actualService); + } +} From 5fc07d88d174e9c4f50db75df2f1ab39ba7ee696 Mon Sep 17 00:00:00 2001 From: Eugene Ritter Date: Wed, 11 Nov 2020 11:03:03 -0600 Subject: [PATCH 579/685] test From 4bf939d6af6d5db218aff2931e8feafb87ec79d8 Mon Sep 17 00:00:00 2001 From: Eugene Ritter Date: Wed, 11 Nov 2020 20:15:50 -0600 Subject: [PATCH 580/685] PhpStan cleanup --- src/Provider/ServiceProviderLoaderTrait.php | 1 - tests/TestCase/PluginTest.php | 13 ------------- 2 files changed, 14 deletions(-) diff --git a/src/Provider/ServiceProviderLoaderTrait.php b/src/Provider/ServiceProviderLoaderTrait.php index 770826647..ccfc0183c 100644 --- a/src/Provider/ServiceProviderLoaderTrait.php +++ b/src/Provider/ServiceProviderLoaderTrait.php @@ -23,7 +23,6 @@ */ trait ServiceProviderLoaderTrait { - /** * Load a service defined in configuration $loaderKey * diff --git a/tests/TestCase/PluginTest.php b/tests/TestCase/PluginTest.php index 24b4754ac..d4fedf44f 100644 --- a/tests/TestCase/PluginTest.php +++ b/tests/TestCase/PluginTest.php @@ -13,26 +13,13 @@ namespace CakeDC\Users\Test\TestCase; -use Authentication\Authenticator\SessionAuthenticator; -use Authentication\Authenticator\TokenAuthenticator; -use Authentication\Identifier\JwtSubjectIdentifier; -use Authentication\Identifier\PasswordIdentifier; -use Authentication\Identifier\TokenIdentifier; use Authentication\Middleware\AuthenticationMiddleware; -use Authorization\AuthorizationService; use Authorization\Middleware\AuthorizationMiddleware; use Authorization\Middleware\RequestAuthorizationMiddleware; -use Authorization\Policy\ResolverCollection; use Cake\Core\Configure; use Cake\Http\MiddlewareQueue; -use Cake\Http\Response; -use Cake\Http\ServerRequest; -use Cake\Http\ServerRequestFactory; use Cake\TestSuite\IntegrationTestTrait; use Cake\TestSuite\TestCase; -use CakeDC\Auth\Authentication\AuthenticationService as CakeDCAuthenticationService; -use CakeDC\Auth\Authenticator\FormAuthenticator; -use CakeDC\Auth\Authenticator\TwoFactorAuthenticator; use CakeDC\Auth\Middleware\TwoFactorMiddleware; use CakeDC\Users\Middleware\SocialAuthMiddleware; use CakeDC\Users\Middleware\SocialEmailMiddleware; From 32eea629aa8c32537e5d2527184765d523c569f5 Mon Sep 17 00:00:00 2001 From: Eugene Ritter Date: Thu, 12 Nov 2020 19:59:47 -0600 Subject: [PATCH 581/685] Unreachable return statement preventing phpstan analysis from completing. --- src/Shell/UsersShell.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 89b62629f..84743669a 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -340,8 +340,6 @@ protected function _updateUser($username, $data) $user = $this->Users->find()->where(['username' => $username])->first(); if (!is_object($user)) { $this->abort(__d('cake_d_c/users', 'The user was not found.')); - - return false; } /** * @var \Cake\Datasource\EntityInterface $user From d906a6efde741b86600da8131f5cdf6305855372 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Fri, 27 Nov 2020 15:01:59 +0300 Subject: [PATCH 582/685] change api token command --- .semver | 2 +- CHANGELOG.md | 3 +++ README.md | 4 ++-- src/Shell/UsersShell.php | 31 +++++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/.semver b/.semver index 1f812fd69..a382f29ec 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 9 :minor: 0 -:patch: 4 +:patch: 5 :special: '' diff --git a/CHANGELOG.md b/CHANGELOG.md index baeeb5ce2..8cd7ec4d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ Releases for CakePHP 4 * Next * +* 9.0.5 + * Added change api token shell command + * 9.0.4 * Fixed deprecations and stan issues * Improved docs diff --git a/README.md b/README.md index d230e53be..cd82b3579 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.3 | stable | -| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.3 | stable | +| ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.5 | stable | +| ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.5 | stable | | ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | | ^3.7 <4.0 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | | 3.6 | [8.1](https://github.com/cakedc/users/tree/8.1.0) | 8.1.0 | stable | diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 84743669a..c6dca6b8c 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -56,6 +56,9 @@ public function getOptionParser(): ConsoleOptionParser ->addSubcommand('changeRole', [ 'help' => __d('cake_d_c/users', 'Change the role for an specific user'), ]) + ->addSubcommand('changeApiToken', [ + 'help' => __d('cake_d_c/users', 'Change the api token for an specific user'), + ]) ->addSubcommand('deactivateUser', [ 'help' => __d('cake_d_c/users', 'Deactivate an specific user'), ]) @@ -193,6 +196,34 @@ public function changeRole() $this->out(__d('cake_d_c/users', 'New role: {0}', $savedUser->role)); } + /** + * Change api token for a user + * + * Arguments: + * + * - Username + * - Token to be set + * + * @return void + */ + public function changeApiToken() + { + $username = Hash::get($this->args, 0); + $token = Hash::get($this->args, 1); + if (empty($username)) { + $this->abort(__d('cake_d_c/users', 'Please enter a username.')); + } + if (empty($token)) { + $this->abort(__d('cake_d_c/users', 'Please enter a token.')); + } + $data = [ + 'api_token' => $token, + ]; + $savedUser = $this->_updateUser($username, $data); + $this->out(__d('cake_d_c/users', 'Api token changed for user: {0}', $username)); + $this->out(__d('cake_d_c/users', 'New token: {0}', $savedUser->api_token)); + } + /** * Activate an specific user * From a2103c60cdfe819023e1d3cc18ac521f4c9bec12 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Fri, 11 Dec 2020 20:52:54 +0300 Subject: [PATCH 583/685] upgrade to lastest cakephp 4.x --- .semver | 4 ++-- composer.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.semver b/.semver index a382f29ec..3665cc1e1 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 9 -:minor: 0 -:patch: 5 +:minor: 1 +:patch: 0 :special: '' diff --git a/composer.json b/composer.json index 96e3b0b23..7395b49fa 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "minimum-stability": "dev", "require": { "php": ">=7.2.0", - "cakephp/cakephp": "^4.0.0", + "cakephp/cakephp": "^4.0", "cakedc/auth": "^6.0.0", "cakephp/authorization": "^2.0.0", "cakephp/authentication": "^2.0.0" From 89f93a9098572722ab1db2d0b706657ab3166e2f Mon Sep 17 00:00:00 2001 From: Dieter Gribnitz Date: Mon, 18 Jan 2021 14:35:59 +0200 Subject: [PATCH 584/685] Update users.php I get deprication warnings when trying to log out. Config key `expire` is deprecated, use `expires` instead. - /var/www/html/vendor/cakephp/authentication/src/Authenticator/CookieAuthenticator.php Config key `httpOnly` is deprecated, use `httponly` instead. - /var/www/html/vendor/cakephp/authentication/src/Authenticator/CookieAuthenticator.php Changing these values fixes the issue for me Currently running CakePHP 4.1.7 --- config/users.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/users.php b/config/users.php index 3c535f7db..e927ea4d4 100644 --- a/config/users.php +++ b/config/users.php @@ -92,8 +92,8 @@ 'Cookie' => [ 'name' => 'remember_me', 'Config' => [ - 'expire' => new \DateTime('+1 month'), - 'httpOnly' => true, + 'expires' => new \DateTime('+1 month'), + 'httponly' => true, ] ] ], @@ -150,8 +150,8 @@ 'skipTwoFactorVerify' => true, 'rememberMeField' => 'remember_me', 'cookie' => [ - 'expire' => new \DateTime('+1 month'), - 'httpOnly' => true, + 'expires' => new \DateTime('+1 month'), + 'httponly' => true, ], 'urlChecker' => 'Authentication.CakeRouter', ], From 0309e669ece9a574088cb5808a720c5849167283 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Mon, 25 Jan 2021 12:00:06 -0400 Subject: [PATCH 585/685] add event afterEmailTokenValidation --- src/Controller/Traits/UserValidationTrait.php | 1 + src/Plugin.php | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index d746a4eb4..59ed8aad7 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -42,6 +42,7 @@ public function validate($type = null, $token = null) try { $result = $this->getUsersTable()->validate($token, 'activateUser'); if ($result) { + $this->dispatchEvent(Plugin::EVENT_AFTER_EMAIL_TOKEN_VALIDATION, ['user' => $result]); $this->Flash->success(__d('cake_d_c/users', 'User account validated successfully')); } else { $this->Flash->error(__d('cake_d_c/users', 'User account could not be validated')); diff --git a/src/Plugin.php b/src/Plugin.php index 8ad5ba6fd..9599b1c62 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -42,6 +42,7 @@ class Plugin extends BasePlugin implements AuthenticationServiceProviderInterfac public const EVENT_SOCIAL_LOGIN_EXISTING_ACCOUNT = 'Users.Global.socialLoginExistingAccount'; public const EVENT_ON_EXPIRED_TOKEN = 'Users.Global.onExpiredToken'; public const EVENT_AFTER_RESEND_TOKEN_VALIDATION = 'Users.Global.afterResendTokenValidation'; + public const EVENT_AFTER_EMAIL_TOKEN_VALIDATION = 'Users.Global.afterEmailTokenValidation'; /** * Returns an authentication service instance. From 7fd4027650883d4035f09c99a2422f17d4355d8b Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Mon, 25 Jan 2021 16:10:26 -0400 Subject: [PATCH 586/685] update documentation --- Docs/Documentation/Events.md | 14 ++++++++++++++ src/Controller/Traits/UserValidationTrait.php | 5 ++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md index d407316aa..eedf5965d 100644 --- a/Docs/Documentation/Events.md +++ b/Docs/Documentation/Events.md @@ -34,3 +34,17 @@ own business, for example $this->register(); $this->render('register'); } + + +How to make an autologin using `EVENT_AFTER_EMAIL_TOKEN_VALIDATION` event + +```php +EventManager::instance()->on( + \CakeDC\Users\Plugin::EVENT_AFTER_EMAIL_TOKEN_VALIDATION, + function($event){ + $users = $this->getTableLocator()->get('Users'); + $user = $users->get($event->getData('user')->id); + $this->Authentication->setIdentity($user); + } +); +``` diff --git a/src/Controller/Traits/UserValidationTrait.php b/src/Controller/Traits/UserValidationTrait.php index 59ed8aad7..16bcf90a0 100644 --- a/src/Controller/Traits/UserValidationTrait.php +++ b/src/Controller/Traits/UserValidationTrait.php @@ -42,7 +42,10 @@ public function validate($type = null, $token = null) try { $result = $this->getUsersTable()->validate($token, 'activateUser'); if ($result) { - $this->dispatchEvent(Plugin::EVENT_AFTER_EMAIL_TOKEN_VALIDATION, ['user' => $result]); + $event = $this->dispatchEvent(Plugin::EVENT_AFTER_EMAIL_TOKEN_VALIDATION, ['user' => $result]); + if (!empty($event) && is_array($event->getResult())) { + return $this->redirect($event->getResult()); + } $this->Flash->success(__d('cake_d_c/users', 'User account validated successfully')); } else { $this->Flash->error(__d('cake_d_c/users', 'User account could not be validated')); From 84b01824564559831fe76a2df0b0dbc5d0adad07 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Tue, 26 Jan 2021 08:09:28 -0400 Subject: [PATCH 587/685] add unittest --- .../TestCase/Controller/Traits/UserValidationTraitTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index d34a6a726..4b061255c 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -42,6 +42,7 @@ public function setUp(): void */ public function testValidateHappyEmail() { + $event = new Event('event'); $this->_mockFlash(); $user = $this->table->findByToken('token-3')->first(); $this->assertFalse($user->active); @@ -51,6 +52,9 @@ public function testValidateHappyEmail() $this->Trait->expects($this->once()) ->method('redirect') ->with(['action' => 'login']); + $this->Trait->expects($this->once()) + ->method('dispatchEvent') + ->will($this->returnValue($event)); $this->Trait->validate('email', 'token-3'); $user = $this->table->findById($user->id)->first(); $this->assertTrue($user->active); @@ -96,7 +100,7 @@ public function testValidateTokenExpired() * @return void */ public function testValidateTokenExpiredWithOnExpiredEvent() - { + { $event = new Event('event'); $event->setResult([ 'action' => 'newAction', From b58b77f92eec1a5224068d3d46869892f066a5b5 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Tue, 26 Jan 2021 18:37:41 -0400 Subject: [PATCH 588/685] add testValidateHappyEmailWithAfterEmailTokenValidationEvent --- .../Traits/UserValidationTraitTest.php | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php index 4b061255c..584d8596c 100644 --- a/tests/TestCase/Controller/Traits/UserValidationTraitTest.php +++ b/tests/TestCase/Controller/Traits/UserValidationTraitTest.php @@ -42,7 +42,6 @@ public function setUp(): void */ public function testValidateHappyEmail() { - $event = new Event('event'); $this->_mockFlash(); $user = $this->table->findByToken('token-3')->first(); $this->assertFalse($user->active); @@ -52,12 +51,29 @@ public function testValidateHappyEmail() $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 testValidateHappyEmailWithAfterEmailTokenValidationEvent() + { + $event = new Event('event'); + $event->setResult([ + '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', 'token-3'); - $user = $this->table->findById($user->id)->first(); - $this->assertTrue($user->active); } /** @@ -100,7 +116,7 @@ public function testValidateTokenExpired() * @return void */ public function testValidateTokenExpiredWithOnExpiredEvent() - { + { $event = new Event('event'); $event->setResult([ 'action' => 'newAction', From 093b4627be7f680e24ca629e722df94e4b150f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 13 Feb 2021 20:05:35 +0000 Subject: [PATCH 589/685] switch to redirectContains --- .../Traits/Integration/LoginTraitIntegrationTest.php | 6 +++--- tests/TestCase/Controller/UsersControllerTest.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index 0cf5b36cb..982806ea1 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -56,7 +56,7 @@ public function testRedirectToLogin() { $this->enableRetainFlashMessages(); $this->get('/pages/home'); - $this->assertRedirect('/login?redirect=http%3A%2F%2Flocalhost%2Fpages%2Fhome'); + $this->assertRedirectContains('/login?redirect=http%3A%2F%2Flocalhost%2Fpages%2Fhome'); $this->assertFlashMessage('You are not authorized to access that location.'); } @@ -197,7 +197,7 @@ public function testLoginPostRequestRightPasswordIsEnabledOTP() 'username' => 'user-2', 'password' => '12345', ]); - $this->assertRedirect('/verify'); + $this->assertRedirectContains('/verify'); } /** @@ -215,7 +215,7 @@ public function testLoginPostRequestRightPasswordIsEnabledU2f() 'username' => 'user-2', 'password' => '12345', ]); - $this->assertRedirect('/users/u2f'); + $this->assertRedirectContains('/users/u2f'); } /** diff --git a/tests/TestCase/Controller/UsersControllerTest.php b/tests/TestCase/Controller/UsersControllerTest.php index a1f2505a5..1b763b16b 100644 --- a/tests/TestCase/Controller/UsersControllerTest.php +++ b/tests/TestCase/Controller/UsersControllerTest.php @@ -51,7 +51,7 @@ public function testUnauthorizedRedirectCustomCallable() ], ]); $this->get('/users/index'); - $this->assertRedirect('/my/custom/url/'); + $this->assertRedirectContains('/my/custom/url/'); } /** @@ -67,7 +67,7 @@ public function testUnauthorizedRedirectNotLogged() ], ]); $this->get('/users/index'); - $this->assertRedirect('/login?redirect=http%3A%2F%2Flocalhost%2Fusers%2Findex'); + $this->assertRedirectContains('/login?redirect=http%3A%2F%2Flocalhost%2Fusers%2Findex'); } /** @@ -89,6 +89,6 @@ public function testUnauthorizedRedirectLogged() ], ]); $this->get('/users/index'); - $this->assertRedirect('/profile'); + $this->assertRedirectContains('/profile'); } } From 3bcc8f43225d7f4f35d089481e98eef1dabab767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 13 Feb 2021 23:51:57 +0000 Subject: [PATCH 590/685] #github-actions start playing with actions --- .github/codecov.yml | 7 ++ .github/workflows/ci.yml | 147 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 .github/codecov.yml create mode 100644 .github/workflows/ci.yml diff --git a/.github/codecov.yml b/.github/codecov.yml new file mode 100644 index 000000000..87fe2a21f --- /dev/null +++ b/.github/codecov.yml @@ -0,0 +1,7 @@ +codecov: + require_ci_to_pass: yes + +coverage: + range: "90...100" + +comment: false \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..f2e0af410 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,147 @@ +name: CI + +on: + push: + branches: + - 'master' + - '9.next' + pull_request: + branches: + - '*' + schedule: + - cron: "0 0 * * *" + +jobs: + testsuite: + runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + php-version: ['7.2', '7.4', '8.0'] + db-type: [sqlite, mysql, pgsql] + prefer-lowest: [''] + include: + - php-version: '7.2' + db-type: 'mariadb' + - php-version: '7.2' + db-type: 'mysql' + prefer-lowest: 'prefer-lowest' + + steps: + - name: Setup MySQL latest + if: matrix.db-type == 'mysql' && matrix.php-version != '7.2' + run: docker run --rm --name=mysqld -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=cakephp -p 3306:3306 -d mysql --default-authentication-plugin=mysql_native_password --disable-log-bin + + - name: Setup PostgreSQL latest + if: matrix.db-type == 'pgsql' && matrix.php-version != '7.2' + run: docker run --rm --name=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=cakephp -p 5432:5432 -d postgres + + - name: Setup PostgreSQL 9.4 + if: matrix.db-type == 'pgsql' && matrix.php-version == '7.2' + run: docker run --rm --name=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=cakephp -p 5432:5432 -d postgres:9.4 + + - uses: getong/mariadb-action@v1.1 + if: matrix.db-type == 'mariadb' + with: + mysql database: 'cakephp' + mysql root password: 'root' + + - uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + extensions: mbstring, intl, apcu, pdo_${{ matrix.db-type }} + ini-values: apc.enable_cli = 1 + coverage: pcov + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Get date part for cache key + id: key-date + run: echo "::set-output name=date::$(date +'%Y-%m')" + + - name: Cache composer dependencies + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }} + + - name: Install packages + run: | + sudo locale-gen da_DK.UTF-8 + sudo locale-gen de_DE.UTF-8 + - name: composer install + run: | + if ${{ matrix.prefer-lowest == 'prefer-lowest' }}; then + composer update --prefer-lowest --prefer-stable + else + composer update + fi + - name: Setup problem matchers for PHPUnit + if: matrix.php-version == '7.4' && matrix.db-type == 'mysql' + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Run PHPUnit + env: + REDIS_PORT: ${{ job.services.redis.ports['6379'] }} + MEMCACHED_PORT: ${{ job.services.memcached.ports['11211'] }} + run: | + if [[ ${{ matrix.db-type }} == 'sqlite' ]]; then export DB_URL='sqlite:///:memory:'; fi + if [[ ${{ matrix.db-type }} == 'mysql' && ${{ matrix.php-version }} != '7.2' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp'; fi + if [[ ${{ matrix.db-type }} == 'mysql' && ${{ matrix.php-version }} == '7.2' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp?encoding=utf8'; fi + if [[ ${{ matrix.db-type }} == 'mariadb' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp'; fi + if [[ ${{ matrix.db-type }} == 'pgsql' ]]; then export DB_URL='postgres://postgres:postgres@127.0.0.1/postgres'; fi + if [[ ${{ matrix.php-version }} == '7.4' ]]; then + export CODECOVERAGE=1 && vendor/bin/phpunit --verbose --coverage-clover=coverage.xml + else + vendor/bin/phpunit + fi + - name: Submit code coverage + if: matrix.php-version == '7.4' + uses: codecov/codecov-action@v1 + + cs-stan: + name: Coding Standard & Static Analysis + runs-on: ubuntu-18.04 + + steps: + - uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '7.3' + extensions: mbstring, intl, apcu + coverage: none + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Get date part for cache key + id: key-date + run: echo "::set-output name=date::$(date +'%Y-%m')" + + - name: Cache composer dependencies + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }} + + - name: composer install + run: composer stan-setup + + - name: Run PHP CodeSniffer + run: vendor/bin/phpcs --report=checkstyle src/ tests/ + + - name: Run psalm + if: success() || failure() + run: vendor/bin/psalm.phar --output-format=github + + - name: Run phpstan + if: success() || failure() + run: vendor/bin/phpstan.phar analyse --error-format=github \ No newline at end of file From 5466aa10f766cabb163c794345b0e4ba27bcfc78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 13 Feb 2021 23:55:06 +0000 Subject: [PATCH 591/685] #github-actions remove travis --- .travis.yml | 59 ----------------------------------------------------- 1 file changed, 59 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9608f7102..000000000 --- a/.travis.yml +++ /dev/null @@ -1,59 +0,0 @@ -language: php - -dist: xenial - -php: - - 7.2 - - 7.3 - - 7.4 - -sudo: false - -services: - - postgresql - - mysql - -cache: - directories: - - vendor - - $HOME/.composer/cache - -env: - matrix: - - DB=mysql db_dsn='mysql://root@127.0.0.1/cakephp_test?init[]=SET sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"' - - 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.3 - env: PHPCS=1 DEFAULT=0 - - - php: 7.3 - env: PHPSTAN=1 DEFAULT=0 - - - php: 7.3 - env: COVERAGE=1 DEFAULT=0 DB=mysql db_dsn='mysql://root@127.0.0.1/cakephp_test?init[]=SET sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"' - -before_script: - - composer install --prefer-dist --no-interaction - - if [[ $DB == 'mysql' ]]; then mysql -u root -e 'CREATE DATABASE cakephp_test;'; fi - - if [[ $DB == 'pgsql' ]]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi - - if [[ $PHPSTAN = 1 ]]; then composer stan-setup; fi - -script: - - if [[ $DEFAULT = 1 ]]; then composer test; fi - - if [[ $COVERAGE = 1 ]]; then composer coverage-test; fi - - if [[ $PHPCS = 1 ]]; then composer cs-check; fi - - if [[ $PHPSTAN = 1 ]]; then composer stan; fi - -after_success: - - if [[ $COVERAGE = 1 ]]; then bash <(curl -s https://codecov.io/bash); fi - -notifications: - email: false From 6fcfb1ea0a8ad6f2c7f3e179cdac28baf588aef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sat, 13 Feb 2021 23:56:52 +0000 Subject: [PATCH 592/685] #github-actions add branch --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f2e0af410..9d6544a1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,7 @@ on: branches: - 'master' - '9.next' + - 'feature/github-actions' pull_request: branches: - '*' From 552145e7ee47cb5fc83de9c39f7ce3d318436100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 00:16:52 +0000 Subject: [PATCH 593/685] #github-actions fix test --- .../Integration/PasswordManagementTraitIntegrationTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php index 55e3b09e6..47a9e337d 100644 --- a/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/PasswordManagementTraitIntegrationTest.php @@ -45,7 +45,7 @@ public function testRequestResetPassword() } /** - * Test login action with post request + * Test reset password workflow * * @return void */ @@ -70,7 +70,6 @@ public function testRequestResetPasswordPostValidEmail() $this->assertRedirect('/users/change-password'); $fieldName = Configure::read('Users.Key.Session.resetPasswordUserId'); - $this->assertSession($userAfter->id, $fieldName); $this->session([ $fieldName => $userAfter->id, ]); From 822a3efe4abf20bab52fa997951d2a1ffbd2647d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 00:20:06 +0000 Subject: [PATCH 594/685] #github-actions fix actions --- .github/workflows/ci.yml | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d6544a1d..cc47de037 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,9 +3,7 @@ name: CI on: push: branches: - - 'master' - - '9.next' - - 'feature/github-actions' + - '*' pull_request: branches: - '*' @@ -18,35 +16,19 @@ jobs: strategy: fail-fast: false matrix: - php-version: ['7.2', '7.4', '8.0'] + php-version: ['7.3', '7.4', '8.0'] db-type: [sqlite, mysql, pgsql] prefer-lowest: [''] - include: - - php-version: '7.2' - db-type: 'mariadb' - - php-version: '7.2' - db-type: 'mysql' - prefer-lowest: 'prefer-lowest' steps: - name: Setup MySQL latest - if: matrix.db-type == 'mysql' && matrix.php-version != '7.2' + if: matrix.db-type == 'mysql' run: docker run --rm --name=mysqld -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=cakephp -p 3306:3306 -d mysql --default-authentication-plugin=mysql_native_password --disable-log-bin - name: Setup PostgreSQL latest - if: matrix.db-type == 'pgsql' && matrix.php-version != '7.2' + if: matrix.db-type == 'pgsql' run: docker run --rm --name=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=cakephp -p 5432:5432 -d postgres - - name: Setup PostgreSQL 9.4 - if: matrix.db-type == 'pgsql' && matrix.php-version == '7.2' - run: docker run --rm --name=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=cakephp -p 5432:5432 -d postgres:9.4 - - - uses: getong/mariadb-action@v1.1 - if: matrix.db-type == 'mariadb' - with: - mysql database: 'cakephp' - mysql root password: 'root' - - uses: actions/checkout@v2 - name: Setup PHP @@ -71,10 +53,6 @@ jobs: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }} - - name: Install packages - run: | - sudo locale-gen da_DK.UTF-8 - sudo locale-gen de_DE.UTF-8 - name: composer install run: | if ${{ matrix.prefer-lowest == 'prefer-lowest' }}; then @@ -87,9 +65,6 @@ jobs: run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - name: Run PHPUnit - env: - REDIS_PORT: ${{ job.services.redis.ports['6379'] }} - MEMCACHED_PORT: ${{ job.services.memcached.ports['11211'] }} run: | if [[ ${{ matrix.db-type }} == 'sqlite' ]]; then export DB_URL='sqlite:///:memory:'; fi if [[ ${{ matrix.db-type }} == 'mysql' && ${{ matrix.php-version }} != '7.2' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp'; fi From d46f478feafca500a6649a37880d44103a1b9de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 00:22:46 +0000 Subject: [PATCH 595/685] #github-actions fix action --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc47de037..af902772e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,9 +67,7 @@ jobs: - name: Run PHPUnit run: | if [[ ${{ matrix.db-type }} == 'sqlite' ]]; then export DB_URL='sqlite:///:memory:'; fi - if [[ ${{ matrix.db-type }} == 'mysql' && ${{ matrix.php-version }} != '7.2' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp'; fi - if [[ ${{ matrix.db-type }} == 'mysql' && ${{ matrix.php-version }} == '7.2' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp?encoding=utf8'; fi - if [[ ${{ matrix.db-type }} == 'mariadb' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp'; fi + if [[ ${{ matrix.db-type }} == 'mysql' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp?encoding=utf8'; fi if [[ ${{ matrix.db-type }} == 'pgsql' ]]; then export DB_URL='postgres://postgres:postgres@127.0.0.1/postgres'; fi if [[ ${{ matrix.php-version }} == '7.4' ]]; then export CODECOVERAGE=1 && vendor/bin/phpunit --verbose --coverage-clover=coverage.xml From 5904f1832cdd442623cffd22b4d806508ae78e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 00:23:46 +0000 Subject: [PATCH 596/685] fix action --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af902772e..19ae505ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,9 @@ name: CI on: push: branches: - - '*' + - 'master' + - '9.next' + - 'feature/github-actions' pull_request: branches: - '*' From d675e1e7996aabbdbfae7993879aa949074aab5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 00:30:44 +0000 Subject: [PATCH 597/685] fix error if subject is null --- src/Model/Behavior/LinkSocialBehavior.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Model/Behavior/LinkSocialBehavior.php b/src/Model/Behavior/LinkSocialBehavior.php index a5f57a2cb..aafc0690a 100644 --- a/src/Model/Behavior/LinkSocialBehavior.php +++ b/src/Model/Behavior/LinkSocialBehavior.php @@ -114,7 +114,9 @@ protected function populateSocialAccount($socialAccount, $data) $accountData['reference'] = $data['id'] ?? null; $accountData['avatar'] = $data['avatar'] ?? null; $accountData['link'] = $data['link'] ?? null; - $accountData['avatar'] = str_replace('normal', 'square', $accountData['avatar']); + if ($accountData['avatar'] ?? null) { + $accountData['avatar'] = str_replace('normal', 'square', $accountData['avatar']); + } $accountData['description'] = $data['bio'] ?? null; $accountData['token'] = $data['credentials']['token'] ?? null; $accountData['token_secret'] = $data['credentials']['secret'] ?? null; From c02280701f32a91eb490892f5804ca81a5d9b48e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 00:39:13 +0000 Subject: [PATCH 598/685] fix error if subject is null --- src/Model/Behavior/SocialBehavior.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 693dc87e5..6c5c2fc02 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -286,7 +286,9 @@ protected function extractAccountData(array $data) $accountData['avatar'] = $data['avatar'] ?? null; $accountData['link'] = $data['link'] ?? null; - $accountData['avatar'] = str_replace('normal', 'square', $accountData['avatar']); + if ($accountData['avatar'] ?? null) { + $accountData['avatar'] = str_replace('normal', 'square', $accountData['avatar']); + } $accountData['description'] = $data['bio'] ?? null; $accountData['token'] = $data['credentials']['token'] ?? null; $accountData['token_secret'] = $data['credentials']['secret'] ?? null; From 268ed01ea164265b834477450eeaa79f896db697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 00:46:31 +0000 Subject: [PATCH 599/685] fix actions config --- .github/workflows/ci.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19ae505ef..d3304e8fd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,6 +62,7 @@ jobs: else composer update fi + - name: Setup problem matchers for PHPUnit if: matrix.php-version == '7.4' && matrix.db-type == 'mysql' run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" @@ -76,6 +77,7 @@ jobs: else vendor/bin/phpunit fi + - name: Submit code coverage if: matrix.php-version == '7.4' uses: codecov/codecov-action@v1 @@ -88,11 +90,12 @@ jobs: - uses: actions/checkout@v2 - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '7.3' - extensions: mbstring, intl, apcu - coverage: none + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + extensions: mbstring, intl, apcu, pdo_${{ matrix.db-type }} + ini-values: apc.enable_cli = 1 + coverage: pcov - name: Get composer cache directory id: composer-cache From 4c319b7d84574880c5beec588152559d71d5cf01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 00:54:35 +0000 Subject: [PATCH 600/685] fix yml --- .github/workflows/ci.yml | 189 +++++++++++++++++++-------------------- 1 file changed, 94 insertions(+), 95 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3304e8fd..7a705816d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,104 +23,103 @@ jobs: prefer-lowest: [''] steps: - - name: Setup MySQL latest - if: matrix.db-type == 'mysql' - run: docker run --rm --name=mysqld -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=cakephp -p 3306:3306 -d mysql --default-authentication-plugin=mysql_native_password --disable-log-bin - - - name: Setup PostgreSQL latest - if: matrix.db-type == 'pgsql' - run: docker run --rm --name=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=cakephp -p 5432:5432 -d postgres - - - uses: actions/checkout@v2 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - extensions: mbstring, intl, apcu, pdo_${{ matrix.db-type }} - ini-values: apc.enable_cli = 1 - coverage: pcov - - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Get date part for cache key - id: key-date - run: echo "::set-output name=date::$(date +'%Y-%m')" - - - name: Cache composer dependencies - uses: actions/cache@v1 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }} - - - name: composer install - run: | - if ${{ matrix.prefer-lowest == 'prefer-lowest' }}; then - composer update --prefer-lowest --prefer-stable - else - composer update - fi - - - name: Setup problem matchers for PHPUnit - if: matrix.php-version == '7.4' && matrix.db-type == 'mysql' - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - name: Run PHPUnit - run: | - if [[ ${{ matrix.db-type }} == 'sqlite' ]]; then export DB_URL='sqlite:///:memory:'; fi - if [[ ${{ matrix.db-type }} == 'mysql' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp?encoding=utf8'; fi - if [[ ${{ matrix.db-type }} == 'pgsql' ]]; then export DB_URL='postgres://postgres:postgres@127.0.0.1/postgres'; fi - if [[ ${{ matrix.php-version }} == '7.4' ]]; then - export CODECOVERAGE=1 && vendor/bin/phpunit --verbose --coverage-clover=coverage.xml - else - vendor/bin/phpunit - fi - - - name: Submit code coverage - if: matrix.php-version == '7.4' - uses: codecov/codecov-action@v1 + - name: Setup MySQL latest + if: matrix.db-type == 'mysql' + run: docker run --rm --name=mysqld -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=cakephp -p 3306:3306 -d mysql --default-authentication-plugin=mysql_native_password --disable-log-bin + + - name: Setup PostgreSQL latest + if: matrix.db-type == 'pgsql' + run: docker run --rm --name=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=cakephp -p 5432:5432 -d postgres + + - uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + extensions: mbstring, intl, apcu, pdo_${{ matrix.db-type }} + ini-values: apc.enable_cli = 1 + coverage: pcov + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Get date part for cache key + id: key-date + run: echo "::set-output name=date::$(date +'%Y-%m')" + + - name: Cache composer dependencies + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }} + + - name: composer install + run: | + if ${{ matrix.prefer-lowest == 'prefer-lowest' }}; then + composer update --prefer-lowest --prefer-stable + else + composer update + fi + + - name: Setup problem matchers for PHPUnit + if: matrix.php-version == '7.4' && matrix.db-type == 'mysql' + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Run PHPUnit + run: | + if [[ ${{ matrix.db-type }} == 'sqlite' ]]; then export DB_URL='sqlite:///:memory:'; fi + if [[ ${{ matrix.db-type }} == 'mysql' ]]; then export DB_URL='mysql://root:root@127.0.0.1/cakephp?encoding=utf8'; fi + if [[ ${{ matrix.db-type }} == 'pgsql' ]]; then export DB_URL='postgres://postgres:postgres@127.0.0.1/postgres'; fi + if [[ ${{ matrix.php-version }} == '7.4' ]]; then + export CODECOVERAGE=1 && vendor/bin/phpunit --verbose --coverage-clover=coverage.xml + else + vendor/bin/phpunit + fi + + - name: Submit code coverage + if: matrix.php-version == '7.4' + uses: codecov/codecov-action@v1 cs-stan: name: Coding Standard & Static Analysis runs-on: ubuntu-18.04 steps: - - uses: actions/checkout@v2 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - extensions: mbstring, intl, apcu, pdo_${{ matrix.db-type }} - ini-values: apc.enable_cli = 1 - coverage: pcov - - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - - name: Get date part for cache key - id: key-date - run: echo "::set-output name=date::$(date +'%Y-%m')" - - - name: Cache composer dependencies - uses: actions/cache@v1 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }} - - - name: composer install - run: composer stan-setup - - - name: Run PHP CodeSniffer - run: vendor/bin/phpcs --report=checkstyle src/ tests/ - - - name: Run psalm - if: success() || failure() - run: vendor/bin/psalm.phar --output-format=github - - - name: Run phpstan - if: success() || failure() - run: vendor/bin/phpstan.phar analyse --error-format=github \ No newline at end of file + - uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '7.3' + extensions: mbstring, intl, apcu + coverage: none + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Get date part for cache key + id: key-date + run: echo "::set-output name=date::$(date +'%Y-%m')" + + - name: Cache composer dependencies + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ steps.key-date.outputs.date }}-${{ hashFiles('composer.json') }}-${{ matrix.prefer-lowest }} + + - name: composer install + run: composer stan-setup + + - name: Run PHP CodeSniffer + run: vendor/bin/phpcs --report=checkstyle src/ tests/ + + - name: Run psalm + if: success() || failure() + run: vendor/bin/psalm.phar --output-format=github + + - name: Run phpstan + if: success() || failure() + run: vendor/bin/phpstan.phar analyse --error-format=github \ No newline at end of file From 86cb29f0304d704b2200aa31b12159eb759a5b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 01:05:25 +0000 Subject: [PATCH 601/685] fix action db setup --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a705816d..7d928c139 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} - extensions: mbstring, intl, apcu, pdo_${{ matrix.db-type }} + extensions: mbstring, intl, apcu, pdo_${{ matrix.db-type }}, ${{ matrix.db-type }} ini-values: apc.enable_cli = 1 coverage: pcov From 4db29460c27f72ddb9c1cf5dd39513c6bd3c5fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 01:06:15 +0000 Subject: [PATCH 602/685] update actions --- .github/workflows/ci.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d928c139..9671a7ab3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,15 +2,10 @@ name: CI on: push: - branches: - - 'master' - - '9.next' - - 'feature/github-actions' + pull_request: branches: - '*' - schedule: - - cron: "0 0 * * *" jobs: testsuite: From 077faed3669cc01350a8963aab5ea84561eb06b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 01:14:26 +0000 Subject: [PATCH 603/685] update actions --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9671a7ab3..253a9240e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} - extensions: mbstring, intl, apcu, pdo_${{ matrix.db-type }}, ${{ matrix.db-type }} + extensions: mbstring, intl, apcu, sqlite, pdo_sqlite, pdo_${{ matrix.db-type }}, ${{ matrix.db-type }} ini-values: apc.enable_cli = 1 coverage: pcov @@ -79,7 +79,7 @@ jobs: cs-stan: name: Coding Standard & Static Analysis - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 @@ -109,7 +109,7 @@ jobs: run: composer stan-setup - name: Run PHP CodeSniffer - run: vendor/bin/phpcs --report=checkstyle src/ tests/ + run: composer cs-check - name: Run psalm if: success() || failure() @@ -117,4 +117,4 @@ jobs: - name: Run phpstan if: success() || failure() - run: vendor/bin/phpstan.phar analyse --error-format=github \ No newline at end of file + run: composer stan \ No newline at end of file From 8ca7df70622462dc16fd80db7fce7f123aac5107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 01:31:56 +0000 Subject: [PATCH 604/685] #github-actions fix stan --- src/Model/Entity/User.php | 1 + src/Shell/UsersShell.php | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 2e1e7e869..27ef8af10 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -27,6 +27,7 @@ * @property bool $is_superuser * @property \Cake\I18n\Time $token_expires * @property string $token + * @property string $api_token * @property array $additional_data * @property \CakeDC\Users\Model\Entity\SocialAccount[] $social_accounts */ diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index c6dca6b8c..56810ab8d 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -220,6 +220,12 @@ public function changeApiToken() 'api_token' => $token, ]; $savedUser = $this->_updateUser($username, $data); + if (!$savedUser) { + $this->err(__d('cake_d_c/users', 'User was not saved, check validation errors')); + } + /** + * @var User $savedUser + */ $this->out(__d('cake_d_c/users', 'Api token changed for user: {0}', $username)); $this->out(__d('cake_d_c/users', 'New token: {0}', $savedUser->api_token)); } From 66cd542250ebc3d951b3006b67a5d116dfeda8b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 01:31:57 +0000 Subject: [PATCH 605/685] fix cs --- src/Shell/UsersShell.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 56810ab8d..146eb2ee8 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -224,7 +224,7 @@ public function changeApiToken() $this->err(__d('cake_d_c/users', 'User was not saved, check validation errors')); } /** - * @var User $savedUser + * @var \CakeDC\Users\Model\Entity\User $savedUser */ $this->out(__d('cake_d_c/users', 'Api token changed for user: {0}', $username)); $this->out(__d('cake_d_c/users', 'New token: {0}', $savedUser->api_token)); From c838b8b087f29926980b4735647e2a83f300c2ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Sun, 14 Feb 2021 01:39:45 +0000 Subject: [PATCH 606/685] fix action and badges --- .github/workflows/ci.yml | 6 +++--- README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 253a9240e..bb98b5723 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,9 +111,9 @@ jobs: - name: Run PHP CodeSniffer run: composer cs-check - - name: Run psalm - if: success() || failure() - run: vendor/bin/psalm.phar --output-format=github +# - name: Run psalm +# if: success() || failure() +# run: vendor/bin/psalm.phar --output-format=github - name: Run phpstan if: success() || failure() diff --git a/README.md b/README.md index 3f4e0311b..3b8ddb439 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ CakeDC Users Plugin =================== -[![Build Status](https://secure.travis-ci.org/CakeDC/users.png?branch=master)](http://travis-ci.org/CakeDC/users) +[![Build Status](https://img.shields.io/github/workflow/status/CakeDC/users/CI/master?style=flat-square)](https://github.com/CakeDC/users/actions?query=workflow%3ACI+branch%3Amaster) [![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) From 6b3452b0913add03d4923e1b6ee9be371bff697c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Sun, 14 Feb 2021 01:48:22 +0000 Subject: [PATCH 607/685] Update .semver --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index 3665cc1e1..a0290e8f4 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 9 -:minor: 1 +:minor: 2 :patch: 0 :special: '' From 434e274f2e7fb69adb9fd67a548621b300d6d058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Sun, 14 Feb 2021 01:50:54 +0000 Subject: [PATCH 608/685] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cd7ec4d4..d8eea9d31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,10 @@ Changelog ========= Releases for CakePHP 4 ------------- -* Next - * +* 9.2.0 + * Switch to github actions + * New event AfterEmailTokenValidation + * Remove deprecations * 9.0.5 * Added change api token shell command From f44b433b531e31508f0de1dfe88800febb585e78 Mon Sep 17 00:00:00 2001 From: Yelitza Parra Date: Fri, 30 Apr 2021 17:08:29 +0200 Subject: [PATCH 609/685] fix typo --- Docs/Documentation/AuthLinkHelper.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/AuthLinkHelper.md b/Docs/Documentation/AuthLinkHelper.md index 76c2a6055..ace2bdeb5 100644 --- a/Docs/Documentation/AuthLinkHelper.md +++ b/Docs/Documentation/AuthLinkHelper.md @@ -2,7 +2,7 @@ AuthLinkHelper ============= The AuthLink 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. -This helper provided two methods that allow you to hide or dispay links and postLinks based on the permissions file. +This helper provide two methods that allow you to hide or display links and postLinks based on the permissions file. No more permissions check in your views ! If the permissions file is update, you do not have to replicate the permissions logic in the views. Setup From dd108c7e0b2094327c169e4ad22136c238834929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Traull=C3=A9?= <613615+jtraulle@users.noreply.github.com> Date: Sun, 2 May 2021 16:35:44 +0200 Subject: [PATCH 610/685] Update link to Authorization middleware doc. --- Docs/Documentation/Authorization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md index f3e14a276..992ffb183 100644 --- a/Docs/Documentation/Authorization.md +++ b/Docs/Documentation/Authorization.md @@ -30,7 +30,7 @@ The default configuration for authorization middleware is: ``` You can check the configuration options available for authorization middleware at the -[official documentation](https://github.com/cakephp/authorization/blob/master/docs/Middleware.md). +[official documentation](https://github.com/cakephp/authorization/blob/master/docs/en/middleware.rst). The `CakeDC/Users.DefaultRedirect` offers additional behavior and config: * If logged user access unauthorized url he is redirected to referer url or '/' if no referer url From be0ccfe566bb435c24af53fbea524f44f85c9b9d Mon Sep 17 00:00:00 2001 From: Rafael Queiroz Date: Thu, 24 Jun 2021 14:04:39 -0300 Subject: [PATCH 611/685] Setting the $user->isNew() = false on PasswordManagementTrait::changePassword --- src/Controller/Traits/PasswordManagementTrait.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 431d04be0..81b34b2d5 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -41,6 +41,8 @@ trait PasswordManagementTrait public function changePassword($id = null) { $user = $this->getUsersTable()->newEntity([], ['validate' => false]); + $user->isNew(false); + $identity = $this->getRequest()->getAttribute('identity'); $identity = $identity ?? []; $userId = $identity['id'] ?? null; From bc324b817db4398d432706906c37812801795b55 Mon Sep 17 00:00:00 2001 From: Rafael Queiroz Date: Thu, 24 Jun 2021 14:08:59 -0300 Subject: [PATCH 612/685] Fixing change password issue --- src/Controller/Traits/PasswordManagementTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 81b34b2d5..b4b0d014d 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -41,7 +41,7 @@ trait PasswordManagementTrait public function changePassword($id = null) { $user = $this->getUsersTable()->newEntity([], ['validate' => false]); - $user->isNew(false); + $user->setNew(false); $identity = $this->getRequest()->getAttribute('identity'); $identity = $identity ?? []; From 1250e29fe5549d6640e047ca6898365ef5bab915 Mon Sep 17 00:00:00 2001 From: Rafael Queiroz Date: Thu, 24 Jun 2021 14:08:59 -0300 Subject: [PATCH 613/685] Fixing change password issue --- src/Controller/Traits/PasswordManagementTrait.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index 431d04be0..b4b0d014d 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -41,6 +41,8 @@ trait PasswordManagementTrait public function changePassword($id = null) { $user = $this->getUsersTable()->newEntity([], ['validate' => false]); + $user->setNew(false); + $identity = $this->getRequest()->getAttribute('identity'); $identity = $identity ?? []; $userId = $identity['id'] ?? null; From 3c093f604851f60699604f44a19de2515d0b573a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 6 Jul 2021 00:13:52 +0100 Subject: [PATCH 614/685] #block-redirect-to-host-not-allowed check if host is allowed before redirecting to external hosts after login --- config/users.php | 5 +++ src/Controller/Component/LoginComponent.php | 40 +++++++++++++++-- .../Integration/LoginTraitIntegrationTest.php | 44 +++++++++++++++++++ 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/config/users.php b/config/users.php index e927ea4d4..f5c9652b5 100644 --- a/config/users.php +++ b/config/users.php @@ -98,6 +98,11 @@ ] ], 'Superuser' => ['allowedToChangePasswords' => false], // able to reset any users password + // list of valid hosts to allow redirects after valid login via the `redirect` query param + 'AllowedRedirectHosts' => [ + 'localhost', + \Cake\Core\Configure::read('App.fullBaseUrl'), + ], ], 'OneTimePasswordAuthenticator' => [ 'checker' => \CakeDC\Auth\Authentication\DefaultOneTimePasswordAuthenticationChecker::class, diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index ad75f1b9d..54b93b31d 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -17,10 +17,12 @@ use Cake\Controller\Component; use Cake\Core\Configure; use Cake\Http\ServerRequest; +use Cake\Log\Log; use CakeDC\Auth\Authentication\AuthenticationService; use CakeDC\Auth\Traits\IsAuthorizedTrait; use CakeDC\Users\Plugin; use CakeDC\Users\Utility\UsersUrl; +use Laminas\Diactoros\Uri; /** * LoginFailure component @@ -146,13 +148,24 @@ protected function afterIdentifyUser($user) { $event = $this->getController()->dispatchEvent(Plugin::EVENT_AFTER_LOGIN, ['user' => $user]); if (is_array($event->getResult())) { + // in this case we don't checkSafeHost the url as the url params are generated by an event return $this->getController()->redirect($event->getResult()); } - $query = $this->getController()->getRequest()->getQueryParams(); + $queryRedirect = $this->getController()->getRequest()->getQuery('redirect'); $redirectUrl = $this->getController()->Authentication->getConfig('loginRedirect'); - if ($this->isAuthorized($query['redirect'] ?? null)) { - $redirectUrl = $query['redirect']; + if (!$this->checkSafeHost($queryRedirect)) { + $userId = $user['id'] ?? null; + Log::info( + "Unsafe redirect `$queryRedirect` ignored, user id `{$userId}` " . + "redirected to `$redirectUrl` after successful login" + ); + $queryRedirect = $redirectUrl; + } + // even if the host is safe, we need to check if the url is authorized for the given user + // this check ignores the host + if ($this->isAuthorized($queryRedirect ?? null)) { + $redirectUrl = $queryRedirect; } return $this->getController()->redirect($redirectUrl); @@ -184,4 +197,25 @@ protected function handlePasswordRehash($service, $user, \Cake\Http\ServerReques break; } } + + /** + * Check if there is a host defined in the $queryRedirect and it's in the allowed list of hosts + * + * @param string|null $queryRedirect redirect url + * @return bool + */ + protected function checkSafeHost(?string $queryRedirect = null): bool + { + if ($queryRedirect === null) { + return true; + } + + $uri = new Uri($queryRedirect); + $host = $uri->getHost(); + if (!$host) { + return true; + } + + return in_array($host, Configure::read('Users.AllowedRedirectHosts')); + } } diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index 982806ea1..9f6aa9aa3 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -240,4 +240,48 @@ public function testLogoutNoUser() $this->get('/logout'); $this->assertRedirect('/login'); } + + /** + * Test redirect should not happen if the host is not defined as a known host + * + * @return void + */ + public function testRedirectAfterLoginToHostUnknown() + { + $this->post('/login?redirect=http://unknown.com/', [ + 'username' => 'user-4', + 'password' => '12345', + ]); + $this->assertRedirect('/pages/home'); + } + + /** + * Test redirect should happen for defaul localhost + * + * @return void + */ + public function testRedirectAfterLoginToAllowedHost() + { + Configure::write('Users.AllowedRedirectHosts', ['example.com']); + $this->post('/login?redirect=http://example.com/login', [ + 'username' => 'user-4', + 'password' => '12345', + ]); + // /login is authorized for this user, and example.com is in the allowed hosts + $this->assertRedirect('http://example.com/login'); + } + + /** + * Test redirect fails if url is not allowed + * + * @return void + */ + public function testRedirectFailsIfUrlNotAllowed() + { + $this->post('/login?redirect=http://localhost/not-allowed', [ + 'username' => 'user-4', + 'password' => '12345', + ]); + $this->assertRedirect('/pages/home'); + } } From 1957f38bb510b2c09af009c651c5095a16d07de2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 6 Jul 2021 00:13:53 +0100 Subject: [PATCH 615/685] fix cs --- config/users.php | 52 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/config/users.php b/config/users.php index f5c9652b5..edb7c72db 100644 --- a/config/users.php +++ b/config/users.php @@ -72,7 +72,7 @@ ], // form key to store the social auth data 'Form' => [ - 'social' => 'social' + 'social' => 'social', ], 'Data' => [ // data key to store the users email @@ -94,8 +94,8 @@ 'Config' => [ 'expires' => new \DateTime('+1 month'), 'httponly' => true, - ] - ] + ], + ], ], 'Superuser' => ['allowedToChangePasswords' => false], // able to reset any users password // list of valid hosts to allow redirects after valid login via the `redirect` query param @@ -117,7 +117,7 @@ // QR-code provider (more on this later) 'qrcodeprovider' => null, // Random Number Generator provider (more on this later) - 'rngprovider' => null + 'rngprovider' => null, ], 'U2f' => [ 'enabled' => false, @@ -126,12 +126,12 @@ // default configuration used to auto-load the Auth Component, override to change the way Auth works 'Auth' => [ 'Authentication' => [ - 'serviceLoader' => \CakeDC\Users\Loader\AuthenticationServiceLoader::class + 'serviceLoader' => \CakeDC\Users\Loader\AuthenticationServiceLoader::class, ], 'AuthenticationComponent' => [ 'load' => true, 'loginRedirect' => '/', - 'requireIdentity' => false + 'requireIdentity' => false, ], 'Authenticators' => [ 'Session' => [ @@ -167,41 +167,41 @@ 'SocialPendingEmail' => [ 'className' => 'CakeDC/Users.SocialPendingEmail', 'skipTwoFactorVerify' => true, - ] + ], ], 'Identifiers' => [ 'Password' => [ 'className' => 'Authentication.Password', 'fields' => [ 'username' => ['username', 'email'], - 'password' => 'password' + 'password' => 'password', ], 'resolver' => [ 'className' => 'Authentication.Orm', - 'finder' => 'active' + 'finder' => 'active', ], ], - "Social" => [ + 'Social' => [ 'className' => 'CakeDC/Users.Social', - 'authFinder' => 'active' + 'authFinder' => 'active', ], 'Token' => [ 'className' => 'Authentication.Token', 'tokenField' => 'api_token', 'resolver' => [ 'className' => 'Authentication.Orm', - 'finder' => 'active' + 'finder' => 'active', ], - ] + ], ], - "Authorization" => [ + 'Authorization' => [ 'enable' => true, - 'serviceLoader' => \CakeDC\Users\Loader\AuthorizationServiceLoader::class + 'serviceLoader' => \CakeDC\Users\Loader\AuthorizationServiceLoader::class, ], 'AuthorizationMiddleware' => [ 'unauthorizedHandler' => [ 'className' => 'CakeDC/Users.DefaultRedirect', - ] + ], ], 'AuthorizationComponent' => [ 'enabled' => true, @@ -209,7 +209,7 @@ 'RbacPolicy' => [], 'PasswordRehash' => [ 'identifiers' => ['Password'], - ] + ], ], 'OAuth' => [ 'providers' => [ @@ -223,7 +223,7 @@ 'redirectUri' => Router::fullBaseUrl() . '/auth/facebook', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/facebook', 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/facebook', - ] + ], ], 'twitter' => [ 'service' => 'CakeDC\Auth\Social\Service\OAuth1Service', @@ -233,7 +233,7 @@ 'redirectUri' => Router::fullBaseUrl() . '/auth/twitter', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/twitter', 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/twitter', - ] + ], ], 'linkedIn' => [ 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', @@ -243,7 +243,7 @@ 'redirectUri' => Router::fullBaseUrl() . '/auth/linkedIn', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/linkedIn', 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/linkedIn', - ] + ], ], 'instagram' => [ 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', @@ -253,7 +253,7 @@ 'redirectUri' => Router::fullBaseUrl() . '/auth/instagram', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/instagram', 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/instagram', - ] + ], ], 'google' => [ 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', @@ -264,7 +264,7 @@ 'redirectUri' => Router::fullBaseUrl() . '/auth/google', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/google', 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/google', - ] + ], ], 'amazon' => [ 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', @@ -274,7 +274,7 @@ 'redirectUri' => Router::fullBaseUrl() . '/auth/amazon', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/amazon', 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/amazon', - ] + ], ], 'cognito' => [ 'service' => 'CakeDC\Auth\Social\Service\OAuth2Service', @@ -284,11 +284,11 @@ 'redirectUri' => Router::fullBaseUrl() . '/auth/cognito', 'linkSocialUri' => Router::fullBaseUrl() . '/link-social/cognito', 'callbackLinkSocialUri' => Router::fullBaseUrl() . '/callback-link-social/cognito', - 'scope' => 'email openid' - ] + 'scope' => 'email openid', + ], ], ], - ] + ], ]; return $config; From 639fc6b8b6eb18cd87317a4d3ec04a16330b47da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 6 Jul 2021 15:41:46 +0100 Subject: [PATCH 616/685] #block-redirect-to-host-not-allowed fix host extraction from fullBaseUrl and add more tests --- config/users.php | 23 +++++++++++++++---- .../Integration/LoginTraitIntegrationTest.php | 10 ++++++++ .../Controller/UsersControllerTest.php | 2 +- tests/bootstrap.php | 7 +++++- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/config/users.php b/config/users.php index edb7c72db..e6e8e502c 100644 --- a/config/users.php +++ b/config/users.php @@ -10,7 +10,25 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +use Cake\Core\Configure; +use Cake\Log\Log; use Cake\Routing\Router; +use Laminas\Diactoros\Uri; + +$allowedRedirectHosts = [ + 'localhost', +]; +if (Configure::read('App.fullBaseUrl')) { + try { + $uri = new Uri(Configure::read('App.fullBaseUrl')); + $fullBaseHost = $uri->getHost(); + if ($fullBaseHost) { + $allowedRedirectHosts[] = $fullBaseHost; + } + } catch (Exception $ex) { + Log::warning("Invalid host from App.fullBasedUrl in CakeDC/Users configuration: " . $ex->getMessage()); + } +} $config = [ 'Users' => [ @@ -99,10 +117,7 @@ ], 'Superuser' => ['allowedToChangePasswords' => false], // able to reset any users password // list of valid hosts to allow redirects after valid login via the `redirect` query param - 'AllowedRedirectHosts' => [ - 'localhost', - \Cake\Core\Configure::read('App.fullBaseUrl'), - ], + 'AllowedRedirectHosts' => $allowedRedirectHosts, ], 'OneTimePasswordAuthenticator' => [ 'checker' => \CakeDC\Auth\Authentication\DefaultOneTimePasswordAuthenticationChecker::class, diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index 9f6aa9aa3..0e002ad53 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -271,6 +271,16 @@ public function testRedirectAfterLoginToAllowedHost() $this->assertRedirect('http://example.com/login'); } + public function testRedirectAfterLoginToFullBase(): void + { + $this->post('/login?redirect=http://example.com/login', [ + 'username' => 'user-4', + 'password' => '12345', + ]); + // /login is authorized for this user, and example.com is in the allowed hosts + $this->assertRedirect('http://example.com/login'); + } + /** * Test redirect fails if url is not allowed * diff --git a/tests/TestCase/Controller/UsersControllerTest.php b/tests/TestCase/Controller/UsersControllerTest.php index 1b763b16b..9cebd1f89 100644 --- a/tests/TestCase/Controller/UsersControllerTest.php +++ b/tests/TestCase/Controller/UsersControllerTest.php @@ -85,7 +85,7 @@ public function testUnauthorizedRedirectLogged() $this->session(['Auth' => $user]); $this->configRequest([ 'headers' => [ - 'REFERER' => 'http://localhost/profile', + 'REFERER' => 'http://example.com/profile', ], ]); $this->get('/users/index'); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 212a3b467..e9818da53 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -118,7 +118,7 @@ class_alias('TestApp\Controller\AppController', 'App\Controller\AppController'); 'dir' => 'src', 'webroot' => WEBROOT_DIR, 'wwwRoot' => WWW_ROOT, - 'fullBaseUrl' => 'http://localhost', + 'fullBaseUrl' => 'http://example.com', 'imageBaseUrl' => 'img/', 'jsBaseUrl' => 'js/', 'cssBaseUrl' => 'css/', @@ -131,3 +131,8 @@ class_alias('TestApp\Controller\AppController', 'App\Controller\AppController'); Plugin::getCollection()->add(new \CakeDC\Users\Plugin()); session_id('cli'); + +\Cake\Core\Configure::write('Users.AllowedRedirectHosts', [ + 'localhost', + 'example.com', +]); From 28accf61f22e815314b976b643cf8f8f596b3b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Gonz=C3=A1lez?= Date: Tue, 6 Jul 2021 15:41:47 +0100 Subject: [PATCH 617/685] fix cs --- config/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index e6e8e502c..4b52272ed 100644 --- a/config/users.php +++ b/config/users.php @@ -26,7 +26,7 @@ $allowedRedirectHosts[] = $fullBaseHost; } } catch (Exception $ex) { - Log::warning("Invalid host from App.fullBasedUrl in CakeDC/Users configuration: " . $ex->getMessage()); + Log::warning('Invalid host from App.fullBasedUrl in CakeDC/Users configuration: ' . $ex->getMessage()); } } From b4bc71b6b249d8c04ea7b4af9e48af97fba78ba1 Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 28 Jul 2021 23:38:39 +0100 Subject: [PATCH 618/685] show errors based on config --- config/users.php | 2 ++ src/Controller/Traits/RegisterTrait.php | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/config/users.php b/config/users.php index e927ea4d4..0d704e6a9 100644 --- a/config/users.php +++ b/config/users.php @@ -40,6 +40,8 @@ 'ensureActive' => false, // default role name used in registration 'defaultRole' => 'user', + // show verbose error to users + 'ShowVerboseError' => true, ], 'reCaptcha' => [ // reCaptcha key goes here diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 49b43d3be..0661b6b08 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -31,8 +31,8 @@ trait RegisterTrait /** * Register a new user * - * @throws \Cake\Http\Exception\NotFoundException * @return mixed + * @throws \Cake\Http\Exception\NotFoundException */ public function register() { @@ -73,6 +73,12 @@ public function register() $userSaved = $usersTable->register($user, $data, $options); if ($userSaved) { return $this->_afterRegister($userSaved); + } elseif (Configure::read('Users.Registration.ShowVerboseError')) { + $errors = \Collection($user->getErrors())->unfold()->toArray(); + foreach ($errors as $error) { + $this->Flash->error(__($error)); + } + return; } else { $this->set(compact('user')); $this->Flash->error(__d('cake_d_c/users', 'The user could not be saved')); @@ -98,9 +104,14 @@ public function register() } $userSaved = $usersTable->register($user, $requestData, $options); - if (!$userSaved) { + if (!$userSaved && Configure::read('Users.Registration.ShowVerboseError')) { + $errors = \Collection($user->getErrors())->unfold()->toArray(); + foreach ($errors as $error) { + $this->Flash->error(__($error)); + } + return; + } elseif (!$userSaved) { $this->Flash->error(__d('cake_d_c/users', 'The user could not be saved')); - return; } From 359a9c30d903a4cd1bba934f696fb8d557ae0062 Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 28 Jul 2021 23:40:51 +0100 Subject: [PATCH 619/685] update documentation --- Docs/Documentation/Configuration.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index dea40fd4d..5957c6689 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -101,6 +101,8 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use 'ensureActive' => false, // default role name used in registration 'defaultRole' => 'user', + // show verbose error to users + 'ShowVerboseError' => true, ], 'Tos' => [ // determines if the user should include tos accepted From f4822182d7eed1afe1175fd551917907a48438d5 Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 28 Jul 2021 23:46:50 +0100 Subject: [PATCH 620/685] Set default config to false --- Docs/Documentation/Configuration.md | 2 +- config/users.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 5957c6689..72b60698a 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -102,7 +102,7 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use // default role name used in registration 'defaultRole' => 'user', // show verbose error to users - 'ShowVerboseError' => true, + 'ShowVerboseError' => false, ], 'Tos' => [ // determines if the user should include tos accepted diff --git a/config/users.php b/config/users.php index 0d704e6a9..f5619aeb1 100644 --- a/config/users.php +++ b/config/users.php @@ -41,7 +41,7 @@ // default role name used in registration 'defaultRole' => 'user', // show verbose error to users - 'ShowVerboseError' => true, + 'ShowVerboseError' => false, ], 'reCaptcha' => [ // reCaptcha key goes here From 68e21f7d8e4aff31fd5a0d9c6104b18473ee6c02 Mon Sep 17 00:00:00 2001 From: Peter Date: Thu, 29 Jul 2021 22:20:45 +0100 Subject: [PATCH 621/685] added test case --- .../Controller/Traits/RegisterTraitTest.php | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index fcb08a03f..f5b35b5e5 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -426,4 +426,69 @@ public function testRegisterLoggedInUserNotAllowed() $this->Trait->register(); } + + + /** + * test + * + * @return void + */ + public function testNotShowingVerboseErrorOnRegisterWithDefaultConfig() + { + //register user and not validate the email + $this->testRegister(); + + $this->_mockRequestPost(); + $this->_mockAuthentication(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('The user could not be saved'); + + $this->Trait->getRequest()->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(); + } + + /** + * test + * + * @return void + */ + public function testShowingVerboseErrorOnRegisterWithUpdatedConfig() + { + //register user and not validate the email + $this->testRegister(); + + $this->_mockRequestPost(); + $this->_mockAuthentication(); + $this->_mockFlash(); + $this->_mockDispatchEvent(); + + $this->Trait->Flash->expects($this->once()) + ->method('error') + ->with('Email already exists'); + + + $this->Trait->getRequest()->expects($this->once()) + ->method('getData') + ->will($this->returnValue([ + 'username' => 'testRegistration1', + 'password' => 'password', + 'email' => 'test-registration@example.com', + 'password_confirm' => 'password', + 'tos' => 1, + ])); + Configure::write('Users.Registration.ShowVerboseError', true); + $this->Trait->register(); + } } From 3aab7b20e619970c080b8c6ec337fcbaae8c76f7 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 30 Jul 2021 20:25:25 +0100 Subject: [PATCH 622/685] change config key to camel case --- Docs/Documentation/Configuration.md | 2 +- config/users.php | 2 +- src/Controller/Traits/RegisterTrait.php | 10 +++++----- tests/TestCase/Controller/Traits/RegisterTraitTest.php | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index 72b60698a..59017e1d0 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -102,7 +102,7 @@ NOTE: SOME keys were hidden in this doc page, please refer to `vendor/cakedc/use // default role name used in registration 'defaultRole' => 'user', // show verbose error to users - 'ShowVerboseError' => false, + 'showVerboseError' => false, ], 'Tos' => [ // determines if the user should include tos accepted diff --git a/config/users.php b/config/users.php index f5619aeb1..95c7ff48a 100644 --- a/config/users.php +++ b/config/users.php @@ -41,7 +41,7 @@ // default role name used in registration 'defaultRole' => 'user', // show verbose error to users - 'ShowVerboseError' => false, + 'showVerboseError' => false, ], 'reCaptcha' => [ // reCaptcha key goes here diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 0661b6b08..a2d896586 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -71,10 +71,11 @@ public function register() $data = $result->toArray(); $data['password'] = $requestData['password'] ?? null; //since password is a hidden property $userSaved = $usersTable->register($user, $data, $options); + $errors = \collection($user->getErrors())->unfold()->toArray(); if ($userSaved) { return $this->_afterRegister($userSaved); - } elseif (Configure::read('Users.Registration.ShowVerboseError')) { - $errors = \Collection($user->getErrors())->unfold()->toArray(); + } elseif (Configure::read('Users.Registration.showVerboseError') && count($errors) > 0) { + $this->set(compact('user')); foreach ($errors as $error) { $this->Flash->error(__($error)); } @@ -82,7 +83,6 @@ public function register() } else { $this->set(compact('user')); $this->Flash->error(__d('cake_d_c/users', 'The user could not be saved')); - return; } } @@ -104,8 +104,8 @@ public function register() } $userSaved = $usersTable->register($user, $requestData, $options); - if (!$userSaved && Configure::read('Users.Registration.ShowVerboseError')) { - $errors = \Collection($user->getErrors())->unfold()->toArray(); + $errors = \collection($user->getErrors())->unfold()->toArray(); + if (!$userSaved && Configure::read('Users.Registration.showVerboseError') && count($errors) > 0) { foreach ($errors as $error) { $this->Flash->error(__($error)); } diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index f5b35b5e5..e08984cbd 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -488,7 +488,7 @@ public function testShowingVerboseErrorOnRegisterWithUpdatedConfig() 'password_confirm' => 'password', 'tos' => 1, ])); - Configure::write('Users.Registration.ShowVerboseError', true); + Configure::write('Users.Registration.showVerboseError', true); $this->Trait->register(); } } From 2870020892ef82406a49b53e124ffc94482af816 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 30 Jul 2021 20:58:36 +0100 Subject: [PATCH 623/685] fix php code sniffer errrors --- src/Controller/Traits/RegisterTrait.php | 4 ++ .../Controller/Traits/RegisterTraitTest.php | 44 +++++++++---------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index a2d896586..97be4b5f8 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -79,10 +79,12 @@ public function register() foreach ($errors as $error) { $this->Flash->error(__($error)); } + return; } else { $this->set(compact('user')); $this->Flash->error(__d('cake_d_c/users', 'The user could not be saved')); + return; } } @@ -109,9 +111,11 @@ public function register() foreach ($errors as $error) { $this->Flash->error(__($error)); } + return; } elseif (!$userSaved) { $this->Flash->error(__d('cake_d_c/users', 'The user could not be saved')); + return; } diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index e08984cbd..55f5b7da2 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -65,10 +65,10 @@ public function testValidateEmail() public function testRegister() { Router::connect('/users/validate-email/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'validateEmail', - ]); + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'validateEmail', + ]); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); $this->_mockRequestPost(); @@ -128,10 +128,10 @@ public function testRegisterWithEventFalseResult() public function testRegisterWithEventSuccessResult() { Router::connect('/users/validate-email/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'validateEmail', - ]); + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'validateEmail', + ]); $data = [ 'username' => 'testRegistration', @@ -170,10 +170,10 @@ public function testRegisterWithEventSuccessResult() public function testRegisterReCaptcha() { Router::connect('/users/validate-email/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'validateEmail', - ]); + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'validateEmail', + ]); Configure::write('Users.reCaptcha.registration', true); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); @@ -309,10 +309,10 @@ public function testRegisterGet() public function testRegisterRecaptchaDisabled() { Router::connect('/users/validate-email/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'validateEmail', - ]); + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'validateEmail', + ]); Configure::write('Users.Registration.reCaptcha', false); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); @@ -368,10 +368,10 @@ public function testRegisterNotEnabled() public function testRegisterLoggedInUserAllowed() { Router::connect('/users/validate-email/*', [ - 'plugin' => 'CakeDC/Users', - 'controller' => 'Users', - 'action' => 'validateEmail', - ]); + 'plugin' => 'CakeDC/Users', + 'controller' => 'Users', + 'action' => 'validateEmail', + ]); Configure::write('Users.Registration.allowLoggedIn', true); $this->assertEquals(0, $this->table->find()->where(['username' => 'testRegistration'])->count()); @@ -427,7 +427,6 @@ public function testRegisterLoggedInUserNotAllowed() $this->Trait->register(); } - /** * test * @@ -436,7 +435,7 @@ public function testRegisterLoggedInUserNotAllowed() public function testNotShowingVerboseErrorOnRegisterWithDefaultConfig() { //register user and not validate the email - $this->testRegister(); + $this->testRegister(); $this->_mockRequestPost(); $this->_mockAuthentication(); @@ -478,7 +477,6 @@ public function testShowingVerboseErrorOnRegisterWithUpdatedConfig() ->method('error') ->with('Email already exists'); - $this->Trait->getRequest()->expects($this->once()) ->method('getData') ->will($this->returnValue([ From 7c0b80bae8dfbf7ea4d158c41b15a17f7ce76090 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Tue, 17 Aug 2021 09:33:43 +0300 Subject: [PATCH 624/685] improve coding standards --- composer.json | 6 +++--- rector.yml | 4 ---- src/Authenticator/SocialAuthTrait.php | 2 +- src/Controller/Traits/OneTimePasswordVerifyTrait.php | 2 +- src/Controller/Traits/PasswordManagementTrait.php | 2 +- src/Controller/Traits/ProfileTrait.php | 2 +- src/Controller/Traits/RegisterTrait.php | 4 ++-- src/Controller/Traits/U2fTrait.php | 4 ++-- src/Exception/AccountAlreadyActiveException.php | 2 +- src/Exception/AccountNotActiveException.php | 2 +- src/Exception/MissingEmailException.php | 2 +- src/Exception/SocialAuthenticationException.php | 2 +- src/Exception/TokenExpiredException.php | 2 +- src/Exception/UserAlreadyActiveException.php | 2 +- src/Exception/UserNotActiveException.php | 2 +- src/Exception/WrongPasswordException.php | 2 +- src/Identifier/SocialIdentifier.php | 6 ++---- src/Loader/LoginComponentLoader.php | 4 ++-- src/Mailer/UsersMailer.php | 2 +- src/Middleware/SocialAuthMiddleware.php | 2 +- .../UnauthorizedHandler/DefaultRedirectHandler.php | 5 ++--- src/Model/Behavior/BaseTokenBehavior.php | 3 +-- src/Model/Behavior/PasswordBehavior.php | 6 ++---- src/Model/Behavior/RegisterBehavior.php | 5 ++--- src/Model/Behavior/SocialAccountBehavior.php | 9 ++------- src/Model/Behavior/SocialBehavior.php | 8 ++++---- src/Model/Entity/User.php | 6 +++--- src/Model/Table/UsersTable.php | 8 ++------ src/Shell/UsersShell.php | 7 +++---- src/Utility/UsersUrl.php | 2 +- 30 files changed, 47 insertions(+), 68 deletions(-) delete mode 100644 rector.yml diff --git a/composer.json b/composer.json index 7395b49fa..b8be0af96 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,7 @@ "cakephp/authentication": "^2.0.0" }, "require-dev": { - "phpunit/phpunit": "^8.0", + "phpunit/phpunit": "^8", "league/oauth2-facebook": "@stable", "league/oauth2-instagram": "@stable", "league/oauth2-google": "@stable", @@ -86,11 +86,11 @@ "test": "phpunit --stderr", "stan": "phpstan analyse src/", "psalm": "php vendor/psalm/phar/psalm.phar --show-info=false src/ ", - "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:^0.12.7 psalm/phar:~3.8.0 && mv composer.backup composer.json", + "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan:0.12.94 psalm/phar:~4.9.2 && mv composer.backup composer.json", "stan-rebuild-baseline": "phpstan analyse --configuration phpstan.neon --error-format baselineNeon src/ > phpstan-baseline.neon", "psalm-rebuild-baseline": "php vendor/psalm/phar/psalm.phar --show-info=false --set-baseline=psalm-baseline.xml src/", "rector": "rector process src/", - "rector-setup": "cp composer.json composer.backup && composer require --dev rector/rector:^0.4.11 && mv composer.backup composer.json", + "rector-setup": "cp composer.json composer.backup && composer require --dev rector/rector:^0.11.2 && mv composer.backup composer.json", "coverage-test": "phpunit --stderr --coverage-clover=clover.xml" } } diff --git a/rector.yml b/rector.yml deleted file mode 100644 index eaa99e6a6..000000000 --- a/rector.yml +++ /dev/null @@ -1,4 +0,0 @@ -# rector.yaml -services: - Rector\Php\Rector\FunctionLike\ParamTypeDeclarationRector: ~ - Rector\Php\Rector\FunctionLike\ReturnTypeDeclarationRector: ~ diff --git a/src/Authenticator/SocialAuthTrait.php b/src/Authenticator/SocialAuthTrait.php index cb3e7d1c0..9f3cef77c 100644 --- a/src/Authenticator/SocialAuthTrait.php +++ b/src/Authenticator/SocialAuthTrait.php @@ -40,7 +40,7 @@ protected function identify($rawData) } catch (UserNotActiveException $e) { return new Result(null, self::FAILURE_USER_NOT_ACTIVE); } catch (MissingEmailException $exception) { - throw new SocialAuthenticationException(compact('rawData'), null, $exception); + throw new SocialAuthenticationException(['rawData' => $rawData], null, $exception); } } } diff --git a/src/Controller/Traits/OneTimePasswordVerifyTrait.php b/src/Controller/Traits/OneTimePasswordVerifyTrait.php index da3a963d8..9538569a6 100644 --- a/src/Controller/Traits/OneTimePasswordVerifyTrait.php +++ b/src/Controller/Traits/OneTimePasswordVerifyTrait.php @@ -55,7 +55,7 @@ public function verify() $temporarySession['email'], $secret ); - $this->set(compact('secretDataUri')); + $this->set(['secretDataUri' => $secretDataUri]); } if ($this->getRequest()->is('post')) { diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index b4b0d014d..a68b4beff 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -125,7 +125,7 @@ public function changePassword($id = null) $this->log($exception->getMessage()); } } - $this->set(compact('user')); + $this->set(['user' => $user]); $this->set('_serialize', ['user']); } diff --git a/src/Controller/Traits/ProfileTrait.php b/src/Controller/Traits/ProfileTrait.php index d2edc6586..a67ac991c 100644 --- a/src/Controller/Traits/ProfileTrait.php +++ b/src/Controller/Traits/ProfileTrait.php @@ -59,7 +59,7 @@ public function profile($id = null) return $this->redirect($this->getRequest()->referer()); } - $this->set(compact('user', 'isCurrentUser')); + $this->set(['user' => $user, 'isCurrentUser' => $isCurrentUser]); $this->set('_serialize', ['user', 'isCurrentUser']); } } diff --git a/src/Controller/Traits/RegisterTrait.php b/src/Controller/Traits/RegisterTrait.php index 49b43d3be..95f3e1d92 100644 --- a/src/Controller/Traits/RegisterTrait.php +++ b/src/Controller/Traits/RegisterTrait.php @@ -74,7 +74,7 @@ public function register() if ($userSaved) { return $this->_afterRegister($userSaved); } else { - $this->set(compact('user')); + $this->set(['user' => $user]); $this->Flash->error(__d('cake_d_c/users', 'The user could not be saved')); return; @@ -84,7 +84,7 @@ public function register() return $this->redirect($event->getResult()); } - $this->set(compact('user')); + $this->set(['user' => $user]); $this->set('_serialize', ['user']); if (!$this->getRequest()->is('post')) { diff --git a/src/Controller/Traits/U2fTrait.php b/src/Controller/Traits/U2fTrait.php index b19370f76..c5a8596cb 100644 --- a/src/Controller/Traits/U2fTrait.php +++ b/src/Controller/Traits/U2fTrait.php @@ -85,7 +85,7 @@ public function u2fRegister() if (!$data['registration']) { [$registerRequest, $signs] = $this->createU2fLib()->getRegisterData(); $this->getRequest()->getSession()->write('U2f.registerRequest', json_encode($registerRequest)); - $this->set(compact('registerRequest', 'signs')); + $this->set(['registerRequest' => $registerRequest, 'signs' => $signs]); return null; } @@ -146,7 +146,7 @@ public function u2fAuthenticate() } $authenticateRequest = $this->createU2fLib()->getAuthenticateData([$data['registration']]); $this->getRequest()->getSession()->write('U2f.authenticateRequest', json_encode($authenticateRequest)); - $this->set(compact('authenticateRequest')); + $this->set(['authenticateRequest' => $authenticateRequest]); return null; } diff --git a/src/Exception/AccountAlreadyActiveException.php b/src/Exception/AccountAlreadyActiveException.php index d938a749e..f09bac73e 100644 --- a/src/Exception/AccountAlreadyActiveException.php +++ b/src/Exception/AccountAlreadyActiveException.php @@ -15,7 +15,7 @@ use Cake\Core\Exception\Exception; -class AccountAlreadyActiveException extends Exception +class AccountAlreadyActiveException extends \Cake\Core\Exception\CakeException { /** * AccountAlreadyActiveException constructor. diff --git a/src/Exception/AccountNotActiveException.php b/src/Exception/AccountNotActiveException.php index 1d9846a10..75bb2038c 100644 --- a/src/Exception/AccountNotActiveException.php +++ b/src/Exception/AccountNotActiveException.php @@ -15,7 +15,7 @@ use Cake\Core\Exception\Exception; -class AccountNotActiveException extends Exception +class AccountNotActiveException extends \Cake\Core\Exception\CakeException { protected $_messageTemplate = '/a/validate/%s/%s'; diff --git a/src/Exception/MissingEmailException.php b/src/Exception/MissingEmailException.php index fb54ddf9f..a56ae3778 100644 --- a/src/Exception/MissingEmailException.php +++ b/src/Exception/MissingEmailException.php @@ -15,7 +15,7 @@ use Cake\Core\Exception\Exception; -class MissingEmailException extends Exception +class MissingEmailException extends \Cake\Core\Exception\CakeException { /** * MissingEmailException constructor. diff --git a/src/Exception/SocialAuthenticationException.php b/src/Exception/SocialAuthenticationException.php index ae6225081..2b53545e5 100644 --- a/src/Exception/SocialAuthenticationException.php +++ b/src/Exception/SocialAuthenticationException.php @@ -14,7 +14,7 @@ use Cake\Core\Exception\Exception; -class SocialAuthenticationException extends Exception +class SocialAuthenticationException extends \Cake\Core\Exception\CakeException { protected $_messageTemplate = 'Could not autheticate user'; protected $_defaultCode = 400; diff --git a/src/Exception/TokenExpiredException.php b/src/Exception/TokenExpiredException.php index 1a40617f0..f00792e64 100644 --- a/src/Exception/TokenExpiredException.php +++ b/src/Exception/TokenExpiredException.php @@ -15,7 +15,7 @@ use Cake\Core\Exception\Exception; -class TokenExpiredException extends Exception +class TokenExpiredException extends \Cake\Core\Exception\CakeException { /** * TokenExpiredException constructor. diff --git a/src/Exception/UserAlreadyActiveException.php b/src/Exception/UserAlreadyActiveException.php index d7a62c921..ca7b703df 100644 --- a/src/Exception/UserAlreadyActiveException.php +++ b/src/Exception/UserAlreadyActiveException.php @@ -15,7 +15,7 @@ use Cake\Core\Exception\Exception; -class UserAlreadyActiveException extends Exception +class UserAlreadyActiveException extends \Cake\Core\Exception\CakeException { /** * UserAlreadyActiveException constructor. diff --git a/src/Exception/UserNotActiveException.php b/src/Exception/UserNotActiveException.php index e82c41229..873314041 100644 --- a/src/Exception/UserNotActiveException.php +++ b/src/Exception/UserNotActiveException.php @@ -15,7 +15,7 @@ use Cake\Core\Exception\Exception; -class UserNotActiveException extends Exception +class UserNotActiveException extends \Cake\Core\Exception\CakeException { /** * UserNotActiveException constructor. diff --git a/src/Exception/WrongPasswordException.php b/src/Exception/WrongPasswordException.php index 79a6979ff..d17cbd05f 100644 --- a/src/Exception/WrongPasswordException.php +++ b/src/Exception/WrongPasswordException.php @@ -15,7 +15,7 @@ use Cake\Core\Exception\Exception; -class WrongPasswordException extends Exception +class WrongPasswordException extends \Cake\Core\Exception\CakeException { /** * WrongPasswordException constructor. diff --git a/src/Identifier/SocialIdentifier.php b/src/Identifier/SocialIdentifier.php index 98248aee6..7a75ecdc4 100644 --- a/src/Identifier/SocialIdentifier.php +++ b/src/Identifier/SocialIdentifier.php @@ -56,12 +56,10 @@ public function identify(array $credentials) } if ($user->get('social_accounts')) { - $this->dispatchEvent(Plugin::EVENT_AFTER_REGISTER, compact('user')); + $this->dispatchEvent(Plugin::EVENT_AFTER_REGISTER, ['user' => $user]); } - $user = $this->findUser($user)->firstOrFail(); - - return $user; + return $this->findUser($user)->firstOrFail(); } /** diff --git a/src/Loader/LoginComponentLoader.php b/src/Loader/LoginComponentLoader.php index 3d4b05bee..29e6a235c 100644 --- a/src/Loader/LoginComponentLoader.php +++ b/src/Loader/LoginComponentLoader.php @@ -32,7 +32,7 @@ public static function forForm($controller) 'messages' => [ 'FAILURE_INVALID_RECAPTCHA' => __d('cake_d_c/users', 'Invalid reCaptcha'), ], - 'targetAuthenticator' => 'CakeDC\Auth\Authenticator\FormAuthenticator', + 'targetAuthenticator' => \CakeDC\Auth\Authenticator\FormAuthenticator::class, ]; return self::createComponent($controller, 'Auth.FormLoginFailure', $config); @@ -60,7 +60,7 @@ public static function forSocial($controller) 'Your social account has not been validated yet. Please check your inbox for instructions' ), ], - 'targetAuthenticator' => 'CakeDC\Users\Authenticator\SocialAuthenticator', + 'targetAuthenticator' => \CakeDC\Users\Authenticator\SocialAuthenticator::class, ]; return self::createComponent($controller, 'Auth.SocialLoginFailure', $config); diff --git a/src/Mailer/UsersMailer.php b/src/Mailer/UsersMailer.php index 0091880b5..2e4070e96 100644 --- a/src/Mailer/UsersMailer.php +++ b/src/Mailer/UsersMailer.php @@ -107,7 +107,7 @@ protected function socialAccountValidation(EntityInterface $user, EntityInterfac ->setTo($user['email']) ->setSubject($subject) ->setEmailFormat(Message::MESSAGE_BOTH) - ->setViewVars(compact('user', 'socialAccount', 'activationUrl')); + ->setViewVars(['user' => $user, 'socialAccount' => $socialAccount, 'activationUrl' => $activationUrl]); $this ->viewBuilder() ->setTemplate('CakeDC/Users.socialAccountValidation'); diff --git a/src/Middleware/SocialAuthMiddleware.php b/src/Middleware/SocialAuthMiddleware.php index 9abe7fc08..00ca65130 100644 --- a/src/Middleware/SocialAuthMiddleware.php +++ b/src/Middleware/SocialAuthMiddleware.php @@ -41,7 +41,7 @@ class SocialAuthMiddleware implements MiddlewareInterface */ protected function onAuthenticationException(ServerRequest $request, $exception) { - $baseClassName = get_class($exception->getPrevious()); + $baseClassName = $exception->getPrevious() !== null ? get_class($exception->getPrevious()) : self::class; $response = new Response(); if ($baseClassName === MissingEmailException::class) { $this->setErrorMessage($request, __d('cake_d_c/users', 'Please enter your email')); diff --git a/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php index 5681be54c..709a3fe43 100644 --- a/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php +++ b/src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php @@ -107,13 +107,12 @@ protected function addFlashMessage(Session $session, $options): void protected function createFlashMessage($options): array { $message = (array)($options['flash'] ?? []); - $message += [ + + return $message + [ 'message' => __d('cake_d_c/users', 'You are not authorized to access that location.'), 'key' => 'flash', 'element' => 'flash/error', 'params' => [], ]; - - return $message; } } diff --git a/src/Model/Behavior/BaseTokenBehavior.php b/src/Model/Behavior/BaseTokenBehavior.php index 0d4dfbe6e..bd9a5cb8e 100644 --- a/src/Model/Behavior/BaseTokenBehavior.php +++ b/src/Model/Behavior/BaseTokenBehavior.php @@ -54,8 +54,7 @@ protected function _removeValidationToken(EntityInterface $user) { $user['token'] = null; $user['token_expires'] = null; - $result = $this->_table->save($user); - return $result; + return $this->_table->save($user); } } diff --git a/src/Model/Behavior/PasswordBehavior.php b/src/Model/Behavior/PasswordBehavior.php index 52fb92a55..e307d15a0 100644 --- a/src/Model/Behavior/PasswordBehavior.php +++ b/src/Model/Behavior/PasswordBehavior.php @@ -62,10 +62,8 @@ public function resetToken($reference, array $options = []) $user->active = false; $user->activation_date = null; } - if ($options['ensureActive'] ?? false) { - if (!$user['active']) { - throw new UserNotActiveException(__d('cake_d_c/users', 'User not active')); - } + if (($options['ensureActive'] ?? false) && !$user['active']) { + throw new UserNotActiveException(__d('cake_d_c/users', 'User not active')); } $user->updateToken($expiration); $saveResult = $this->_table->save($user); diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 01bc06623..c7799b5ff 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -125,9 +125,8 @@ public function activateUser(EntityInterface $user) $user->activation_date = new \DateTime(); $user->token_expires = null; $user->active = true; - $result = $this->_table->save($user); - return $result; + return $this->_table->save($user); } /** @@ -138,7 +137,7 @@ public function activateUser(EntityInterface $user) * @param string $name name * @return \Cake\Validation\Validator */ - public function buildValidator(Event $event, Validator $validator, $name) + public function buildValidator(\Cake\Event\EventInterface $event, Validator $validator, $name) { if ($name === 'default') { return $this->_emailValidator($validator, $this->validateEmail); diff --git a/src/Model/Behavior/SocialAccountBehavior.php b/src/Model/Behavior/SocialAccountBehavior.php index 271533403..10408a060 100644 --- a/src/Model/Behavior/SocialAccountBehavior.php +++ b/src/Model/Behavior/SocialAccountBehavior.php @@ -38,11 +38,7 @@ class SocialAccountBehavior extends Behavior public function initialize(array $config): void { parent::initialize($config); - $this->_table->belongsTo('Users', [ - 'foreignKey' => 'user_id', - 'joinType' => 'INNER', - 'className' => Configure::read('Users.table'), - ]); + $this->_table->belongsTo('Users')->setForeignKey('user_id')->setJoinType('INNER')->setClassName(Configure::read('Users.table')); } /** @@ -152,8 +148,7 @@ public function resendValidation($provider, $reference) protected function _activateAccount($socialAccount) { $socialAccount->active = true; - $result = $this->_table->save($socialAccount); - return $result; + return $this->_table->save($socialAccount); } } diff --git a/src/Model/Behavior/SocialBehavior.php b/src/Model/Behavior/SocialBehavior.php index 6c5c2fc02..7911ed802 100644 --- a/src/Model/Behavior/SocialBehavior.php +++ b/src/Model/Behavior/SocialBehavior.php @@ -135,7 +135,7 @@ protected function _createSocialUser($data, $options = []) if ($useEmail && empty($email)) { throw new MissingEmailException(__d('cake_d_c/users', 'Email not present')); } else { - $existingUser = $this->_table->find('existingForSocialLogin', compact('email'))->first(); + $existingUser = $this->_table->find('existingForSocialLogin', ['email' => $email])->first(); } $user = $this->_populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration); @@ -150,9 +150,8 @@ protected function _createSocialUser($data, $options = []) } $this->_table->isValidateEmail = $validateEmail; - $result = $this->_table->save($user); - return $result; + return $this->_table->save($user); } /** @@ -169,6 +168,7 @@ protected function _createSocialUser($data, $options = []) */ protected function _populateUser($data, $existingUser, $useEmail, $validateEmail, $tokenExpiration) { + $userData = []; $accountData = $this->extractAccountData($data); $accountData['active'] = true; @@ -247,7 +247,7 @@ public function generateUniqueUsername($username) ->where([$this->_table->aliasField($this->_username) => $username]) ->count(); if ($existingUsername > 0) { - $username = $username . $i; + $username .= $i; $i++; continue; } diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 27ef8af10..3b88c524c 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -81,7 +81,7 @@ protected function _setConfirmPassword($password) */ protected function _setTos($tos) { - if ((bool)$tos === true) { + if ((bool)$tos) { $this->set('tos_date', Time::now()); } @@ -111,7 +111,7 @@ public function getPasswordHasher() { $passwordHasher = Configure::read('Users.passwordHasher'); if (!class_exists($passwordHasher)) { - $passwordHasher = '\Cake\Auth\DefaultPasswordHasher'; + $passwordHasher = \Cake\Auth\DefaultPasswordHasher::class; } return new $passwordHasher(); @@ -172,7 +172,7 @@ protected function _getU2fRegistration() } $object = (object)$this->additional_data['u2f_registration']; - return isset($object->keyHandle) ? $object : null; + return $object->keyHandle !== null ? $object : null; } /** diff --git a/src/Model/Table/UsersTable.php b/src/Model/Table/UsersTable.php index 089f88a9f..4e6954348 100644 --- a/src/Model/Table/UsersTable.php +++ b/src/Model/Table/UsersTable.php @@ -83,10 +83,7 @@ public function initialize(array $config): void $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', - ]); + $this->hasMany('SocialAccounts')->setForeignKey('user_id')->setClassName('CakeDC/Users.SocialAccounts'); } /** @@ -186,9 +183,8 @@ public function validationDefault(Validator $validator): Validator public function validationRegister(Validator $validator) { $validator = $this->validationDefault($validator); - $validator = $this->validationPasswordConfirm($validator); - return $validator; + return $this->validationPasswordConfirm($validator); } /** diff --git a/src/Shell/UsersShell.php b/src/Shell/UsersShell.php index 146eb2ee8..bd38e2e44 100644 --- a/src/Shell/UsersShell.php +++ b/src/Shell/UsersShell.php @@ -321,8 +321,8 @@ protected function _createUser($template) if (!empty($this->params['username'])) { $username = $this->params['username']; } else { - $username = !empty($template['username']) ? - $template['username'] : $this->_generateRandomUsername(); + $username = empty($template['username']) ? + $this->_generateRandomUsername() : $template['username']; } $password = (empty($this->params['password']) ? @@ -387,9 +387,8 @@ protected function _updateUser($username, $data) })->each(function ($value, $field) use (&$user) { $user->{$field} = $value; }); - $savedUser = $this->Users->save($user); - return $savedUser; + return $this->Users->save($user); } /** diff --git a/src/Utility/UsersUrl.php b/src/Utility/UsersUrl.php index 96d05151a..df77dda0c 100644 --- a/src/Utility/UsersUrl.php +++ b/src/Utility/UsersUrl.php @@ -74,7 +74,7 @@ public static function actionParams($action) $prefix = $parts[0]; } - return compact('prefix', 'plugin', 'controller', 'action'); + return ['prefix' => $prefix, 'plugin' => $plugin, 'controller' => $controller, 'action' => $action]; } /** From 6e35abfa4818d6d8468ffa3b00fbd1acd17b6e84 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Tue, 17 Aug 2021 11:49:40 +0300 Subject: [PATCH 625/685] run code style formatter --- src/Exception/AccountAlreadyActiveException.php | 2 -- src/Exception/AccountNotActiveException.php | 2 -- src/Exception/MissingEmailException.php | 2 -- src/Exception/SocialAuthenticationException.php | 2 -- src/Exception/TokenExpiredException.php | 2 -- src/Exception/UserAlreadyActiveException.php | 2 -- src/Exception/UserNotActiveException.php | 2 -- src/Exception/WrongPasswordException.php | 2 -- src/Model/Behavior/RegisterBehavior.php | 1 - 9 files changed, 17 deletions(-) diff --git a/src/Exception/AccountAlreadyActiveException.php b/src/Exception/AccountAlreadyActiveException.php index f09bac73e..4cef96afd 100644 --- a/src/Exception/AccountAlreadyActiveException.php +++ b/src/Exception/AccountAlreadyActiveException.php @@ -13,8 +13,6 @@ namespace CakeDC\Users\Exception; -use Cake\Core\Exception\Exception; - class AccountAlreadyActiveException extends \Cake\Core\Exception\CakeException { /** diff --git a/src/Exception/AccountNotActiveException.php b/src/Exception/AccountNotActiveException.php index 75bb2038c..a7d1f3741 100644 --- a/src/Exception/AccountNotActiveException.php +++ b/src/Exception/AccountNotActiveException.php @@ -13,8 +13,6 @@ namespace CakeDC\Users\Exception; -use Cake\Core\Exception\Exception; - class AccountNotActiveException extends \Cake\Core\Exception\CakeException { protected $_messageTemplate = '/a/validate/%s/%s'; diff --git a/src/Exception/MissingEmailException.php b/src/Exception/MissingEmailException.php index a56ae3778..6ada67bc6 100644 --- a/src/Exception/MissingEmailException.php +++ b/src/Exception/MissingEmailException.php @@ -13,8 +13,6 @@ namespace CakeDC\Users\Exception; -use Cake\Core\Exception\Exception; - class MissingEmailException extends \Cake\Core\Exception\CakeException { /** diff --git a/src/Exception/SocialAuthenticationException.php b/src/Exception/SocialAuthenticationException.php index 2b53545e5..bb9e03bf5 100644 --- a/src/Exception/SocialAuthenticationException.php +++ b/src/Exception/SocialAuthenticationException.php @@ -12,8 +12,6 @@ */ namespace CakeDC\Users\Exception; -use Cake\Core\Exception\Exception; - class SocialAuthenticationException extends \Cake\Core\Exception\CakeException { protected $_messageTemplate = 'Could not autheticate user'; diff --git a/src/Exception/TokenExpiredException.php b/src/Exception/TokenExpiredException.php index f00792e64..ee036ecac 100644 --- a/src/Exception/TokenExpiredException.php +++ b/src/Exception/TokenExpiredException.php @@ -13,8 +13,6 @@ namespace CakeDC\Users\Exception; -use Cake\Core\Exception\Exception; - class TokenExpiredException extends \Cake\Core\Exception\CakeException { /** diff --git a/src/Exception/UserAlreadyActiveException.php b/src/Exception/UserAlreadyActiveException.php index ca7b703df..3490eae6d 100644 --- a/src/Exception/UserAlreadyActiveException.php +++ b/src/Exception/UserAlreadyActiveException.php @@ -13,8 +13,6 @@ namespace CakeDC\Users\Exception; -use Cake\Core\Exception\Exception; - class UserAlreadyActiveException extends \Cake\Core\Exception\CakeException { /** diff --git a/src/Exception/UserNotActiveException.php b/src/Exception/UserNotActiveException.php index 873314041..5533b4447 100644 --- a/src/Exception/UserNotActiveException.php +++ b/src/Exception/UserNotActiveException.php @@ -13,8 +13,6 @@ namespace CakeDC\Users\Exception; -use Cake\Core\Exception\Exception; - class UserNotActiveException extends \Cake\Core\Exception\CakeException { /** diff --git a/src/Exception/WrongPasswordException.php b/src/Exception/WrongPasswordException.php index d17cbd05f..8a4ec0b56 100644 --- a/src/Exception/WrongPasswordException.php +++ b/src/Exception/WrongPasswordException.php @@ -13,8 +13,6 @@ namespace CakeDC\Users\Exception; -use Cake\Core\Exception\Exception; - class WrongPasswordException extends \Cake\Core\Exception\CakeException { /** diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index c7799b5ff..8bc19e513 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -15,7 +15,6 @@ use Cake\Core\Configure; use Cake\Datasource\EntityInterface; -use Cake\Event\Event; use Cake\Mailer\MailerAwareTrait; use Cake\Validation\Validator; use CakeDC\Users\Exception\TokenExpiredException; From 24f4ef55437f15ab16127830aaec2af1ebb2cd9f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 9 Sep 2021 13:15:52 -0300 Subject: [PATCH 626/685] Added section ' Settting user data in session for unit tests' to migration guide --- Docs/Documentation/Migration/8.x-9.0.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Docs/Documentation/Migration/8.x-9.0.md b/Docs/Documentation/Migration/8.x-9.0.md index 7ae2a134c..c375d89cd 100644 --- a/Docs/Documentation/Migration/8.x-9.0.md +++ b/Docs/Documentation/Migration/8.x-9.0.md @@ -111,3 +111,21 @@ if ($user) { //Do stuff } ``` + +Settting user data in session for unit tests +-------------------------------------------- + +Authentication process read and store user data at session key 'Auth' not 'Auth.User' and the +value should be an User object. + +In your integration test class replace this: + +``` +$this->session(['Auth.User' => $userData]); +``` + +with + +``` +$this->session(['Auth' => new \CakeDC\Users\Model\Entity\User($userData)]); +``` \ No newline at end of file From 50ca5d94868eaced1eb9917da4c0006b8b6cc42f Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Thu, 30 Sep 2021 11:18:30 -0400 Subject: [PATCH 627/685] add last_login in users table --- .../20210929202041_AddLastLoginToUsers.php | 24 +++++++++++++++++++ src/Controller/Component/LoginComponent.php | 19 +++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 config/Migrations/20210929202041_AddLastLoginToUsers.php diff --git a/config/Migrations/20210929202041_AddLastLoginToUsers.php b/config/Migrations/20210929202041_AddLastLoginToUsers.php new file mode 100644 index 000000000..e307f3125 --- /dev/null +++ b/config/Migrations/20210929202041_AddLastLoginToUsers.php @@ -0,0 +1,24 @@ +table('users'); + $table->addColumn('last_login', 'datetime', [ + 'default' => null, + 'null' => false, + ]); + $table->update(); + } +} diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index 54b93b31d..81fd1a9b3 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -70,6 +70,7 @@ public function handleLogin($errorOnlyPost, $redirectFailure) if ($result->isValid()) { $user = $request->getAttribute('identity')->getOriginalData(); $this->handlePasswordRehash($service, $user, $request); + $this->updateLastLogin($user); return $this->afterIdentifyUser($user); } @@ -218,4 +219,22 @@ protected function checkSafeHost(?string $queryRedirect = null): bool return in_array($host, Configure::read('Users.AllowedRedirectHosts')); } + + /** + * Update last loging date + * + * @param \CakeDC\Users\Model\Entity\User $user User entity. + * @return void + */ + protected function updateLastLogin($user) + { + $now = \Cake\I18n\FrozenTime::now(); + $user->set('last_login', $now); + $this->getController()->getUsersTable()->updateAll( + ['last_login' => $now], + ['id' => $user->id] + ); + } + + } From 815aea7aeaaa190267c5194d827905ad359f5ec0 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Thu, 30 Sep 2021 15:51:20 -0400 Subject: [PATCH 628/685] update fixtures --- config/Migrations/schema-dump-default.lock | Bin 0 -> 8123 bytes src/Controller/Component/LoginComponent.php | 2 -- tests/Fixture/UsersFixture.php | 3 +++ 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 config/Migrations/schema-dump-default.lock diff --git a/config/Migrations/schema-dump-default.lock b/config/Migrations/schema-dump-default.lock new file mode 100644 index 0000000000000000000000000000000000000000..9c437b3c14deb432447ac8cb12213731dd01e881 GIT binary patch literal 8123 zcmdT}!E)O;4DGk*xF^e5H(ln|?WKoy5A88C8d{=LPGnI-O4(#G`S(6hl0`xC*oo`d zJ~b{x3Iu_N_aG_e;@OFXh-#;-i*EiCS91~lEAQ3q7g@=rbn5m;`b(|l?N7PPRr7Zw zu4&mnBKq*xhXjx1D!K``aUzZzV`}nxU0`P^<}+G^?R7>!{T6?VsCp{>YW!K(WOCx8 zh;mijRllN}@AwHzQRjJdvlKJ@ycSWWREENvdhvH~Wt5a48x=Imq$2@nIa#qdAU?DW!A&8|$;+qJkbHxmMb`DtUd*EGTt@ zlzIQiqXKeyp}r&CD|4?|al}ADjeW-~HI8kW=q7nRYYej)~ze!&hMsu7EUJLzG32|2JA^hvxDeCOf<_St}c}&jx$vo zCv*=vVv#?uD~}QD;w{tzV{_V;SsjhV5O1>zpfgz?2cQnm1){F>vRwqXp|fj~Z7tf< zI7NsevrH38%bcoLPTe{ZqEe5Zz;7r2{JuA_IodT7;q#m+H+R~Tk3ZPD-+a}$>rP&g zR{17N3h6*zHKowXDcpRob39)6x(3(N>Ii1QqMoNS8|T5yJS3XTh!?hugBd26l9y;9 zGa6DBz5%5grv#%dg5Er_e$@PY^##oiVd=Zj)aG3~;0woy%%9kRBJ(T6n$a8KPha#S z>tyx$+~}%}XE@s;NHtw#>apRk5b|U|yh;D3ra(SPT~waj#w4TRb7}Qj+9yiQE2gYN ztA93_5@5OZGQS-Z;6(u(ZE7af!SS`_BXXKJQM9=r#F z+)n@+|3{LXb_Qkla}BjFjrB*M!9#muXHpFylWA&df8v8iCZ2Hd9sBYQ!NLHcUn3cIa-!q+NR*XTD`i!Y9!lu8cEqDKc%X%Zgp{5j zACNL9peE1=nR2Ps9sn23set+h;txEsXNLpv7t*wW0cY#^5|bPQKEiCne$R|SKV=qDtb=~#o#|xA zrYEpf+tuO-)7Z*=f7`+nGtlZb)dS1sfTOgHw3%pIT7oY86xysJbLj>0&EgDzi>EW-3=(OdawB;cdTm Jzn>U=`3=1y0=@tM literal 0 HcmV?d00001 diff --git a/src/Controller/Component/LoginComponent.php b/src/Controller/Component/LoginComponent.php index 81fd1a9b3..7ddbbf420 100644 --- a/src/Controller/Component/LoginComponent.php +++ b/src/Controller/Component/LoginComponent.php @@ -235,6 +235,4 @@ protected function updateLastLogin($user) ['id' => $user->id] ); } - - } diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index 607393d18..3d4146f0b 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -45,6 +45,7 @@ class UsersFixture extends TestFixture 'created' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], 'modified' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], 'additional_data' => ['type' => 'text', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], + 'last_login' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], '_constraints' => [ 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], ], @@ -90,6 +91,7 @@ public function init(): void 'counter' => 1, ], ]), + 'last_login' => '2015-06-24 17:33:54', ], [ 'id' => '00000000-0000-0000-0000-000000000002', @@ -111,6 +113,7 @@ public function init(): void 'role' => 'admin', 'created' => '2015-06-24 17:33:54', 'modified' => '2015-06-24 17:33:54', + 'last_login' => '2015-06-24 17:33:54', ], [ 'id' => '00000000-0000-0000-0000-000000000003', From 1036b6eaf1e7b6e9cbd601bd37c7a34bac839079 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Fri, 1 Oct 2021 12:55:33 -0400 Subject: [PATCH 629/685] add last_login tests --- config/Migrations/20210929202041_AddLastLoginToUsers.php | 2 +- tests/Fixture/UsersFixture.php | 2 +- tests/TestCase/Controller/Traits/LoginTraitTest.php | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/config/Migrations/20210929202041_AddLastLoginToUsers.php b/config/Migrations/20210929202041_AddLastLoginToUsers.php index e307f3125..5a533c250 100644 --- a/config/Migrations/20210929202041_AddLastLoginToUsers.php +++ b/config/Migrations/20210929202041_AddLastLoginToUsers.php @@ -17,7 +17,7 @@ public function change() $table = $this->table('users'); $table->addColumn('last_login', 'datetime', [ 'default' => null, - 'null' => false, + 'null' => true, ]); $table->update(); } diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index 3d4146f0b..9b52ab940 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -45,7 +45,7 @@ class UsersFixture extends TestFixture 'created' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], 'modified' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], 'additional_data' => ['type' => 'text', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], - 'last_login' => ['type' => 'datetime', 'length' => null, 'null' => false, 'default' => null, 'comment' => '', 'precision' => null], + 'last_login' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], '_constraints' => [ 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], ], diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index 66cd4707c..f84429fe8 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -92,6 +92,8 @@ public function testLoginHappy() $user = $this->Trait->getUsersTable()->get('00000000-0000-0000-0000-000000000002'); $passwordBefore = $user['password']; $this->assertNotEmpty($passwordBefore); + $lastLoginBefore = $user['last_login']; + $this->assertNotEmpty($lastLoginBefore); $this->_mockAuthentication($user->toArray(), $failures); $this->Trait->Flash->expects($this->never()) ->method('error'); @@ -130,6 +132,11 @@ public function testLoginHappy() $userAfter = $this->Trait->getUsersTable()->get('00000000-0000-0000-0000-000000000002'); $passwordAfter = $userAfter['password']; $this->assertSame($passwordBefore, $passwordAfter); + + $lastLoginAfter = $userAfter['last_login']; + $this->assertNotEmpty($lastLoginAfter); + $now = \Cake\I18n\FrozenTime::now(); + $this->assertEqualsWithDelta($lastLoginAfter->timestamp, $now->timestamp, 2); } /** From d41afef59d1de45731920bd1f1d675de32616f95 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Fri, 1 Oct 2021 13:07:01 -0400 Subject: [PATCH 630/685] fix getUsersTable method --- phpstan-baseline.neon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 146e9ed85..8eabb7053 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -7,7 +7,7 @@ parameters: - message: "#^Call to an undefined method Cake\\\\Controller\\\\Controller\\:\\:getUsersTable\\(\\)\\.$#" - count: 1 + count: 2 path: src\Controller\Component\LoginComponent.php - From c053503fdd09a26b13a55855972d807b0011f3fd Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Fri, 1 Oct 2021 13:10:03 -0400 Subject: [PATCH 631/685] minor fix --- tests/TestCase/Controller/Traits/LoginTraitTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/TestCase/Controller/Traits/LoginTraitTest.php b/tests/TestCase/Controller/Traits/LoginTraitTest.php index f84429fe8..79d0a860b 100644 --- a/tests/TestCase/Controller/Traits/LoginTraitTest.php +++ b/tests/TestCase/Controller/Traits/LoginTraitTest.php @@ -132,7 +132,6 @@ public function testLoginHappy() $userAfter = $this->Trait->getUsersTable()->get('00000000-0000-0000-0000-000000000002'); $passwordAfter = $userAfter['password']; $this->assertSame($passwordBefore, $passwordAfter); - $lastLoginAfter = $userAfter['last_login']; $this->assertNotEmpty($lastLoginAfter); $now = \Cake\I18n\FrozenTime::now(); From fe0eb2949ebc5a3903972a90bc886f3b49821754 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 21 Oct 2021 08:42:06 -0300 Subject: [PATCH 632/685] Improved doc home with quick doc block and links --- Docs/Home.md | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/Docs/Home.md b/Docs/Home.md index bb757d6e2..b5a151f0b 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -27,6 +27,70 @@ Documentation * [Extending the Plugin](Documentation/Extending-the-Plugin.md) * [Translations](Documentation/Translations.md) +I want to +--------- +* extend the + * [model](Documentation/Extending-the-Plugin.md#extending-the-model-tableentity) + * [controller](Documentation/Extending-the-Plugin.md#extending-the-controller) + * [templates](Documentation/Extending-the-Plugin.md#updating-the-templates) + +* enable or disable + *
+ email validation + Add this to your config/users.php file to disable email validation + + ```php + 'Users.Email.validate' => false, + ``` + or this to enable (default) + + ```php + 'Users.Email.validate' => true, + ``` +
+ *
+ registration + Add this to your config/users.php file to disable registration + + ```php + 'Users.Registration.active' => false, + ``` + or this to enable (default) + + ```php + 'Users.Registration.active' => true, + ``` +
+ *
+ reCaptcha on registration + To enable reCaptcha you need to register your site at google reCaptcha console + and add this to your config/users.php file to enable on registration: + + ```php + 'Users.reCaptcha.registration' => true, + ``` + To disable (default) add this to your config/users.php + + ```php + 'Users.reCaptcha.registration' => false, + ``` +
+ *
+ reCaptcha on login + To enable reCaptcha you need to register your site at google reCaptcha console + and add this to your config/users.php file to enable on login: + + ```php + 'Users.reCaptcha.login' => true, + ``` + To disable (default) add this to your config/users.php + + ```php + 'Users.reCaptcha.login' => false, + ``` +
+ * [social login](./Documentation/SocialAuthentication.md#setup) + Migration guides ---------------- From 30713354a506b8816508cfd2342ea368c56d21ba Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 21 Oct 2021 08:43:10 -0300 Subject: [PATCH 633/685] Improved social authentication doc and removed reference to Configure:write, we recommend to use a custom config/users.php file --- Docs/Documentation/SocialAuthentication.md | 28 ++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Docs/Documentation/SocialAuthentication.md b/Docs/Documentation/SocialAuthentication.md index 27223000e..4c79c4a2b 100644 --- a/Docs/Documentation/SocialAuthentication.md +++ b/Docs/Documentation/SocialAuthentication.md @@ -12,21 +12,25 @@ We currently support the following providers to perform login as well as to link Please [contact us](https://cakedc.com/contact) if you need to support another provider. -The main source code for social integration is provided by ['CakeDC/auth' plugin](https://github.com/cakedc/auth) +The main source code for social integration is provided by ['CakeDC/auth' plugin](https://github.com/cakedc/auth) Setup ----- +By default social login is disabled, to enable you need to create the +Facebook/Twitter applications you want to use and update your file config/users.php with: -Create the Facebook/Twitter applications you want to use and setup the configuration like this: - -Config/bootstrap.php ```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'); +//This enable social login (authentication) +'Users.Social.login' => true, +//This is the required config to setup facebook. +'OAuth.providers.facebook.options.clientId', 'YOUR APP ID'; +'OAuth.providers.facebook.options.clientSecret', 'YOUR APP SECRET'; +//This is the required config to setup twitter +'OAuth.providers.twitter.options.clientId', 'YOUR APP ID'; +'OAuth.providers.twitter.options.clientSecret', 'YOUR APP SECRET'; ``` +Check optional configs at [config/users.php](./../../config/users.php) inside 'OAuth' key + You can also change the default settings for social authenticate: @@ -92,7 +96,7 @@ In your customized users table, add the SocialBehavior with the following config ```php $this->addBehavior('CakeDC/Users.Social', [ - 'username' => 'email' + 'username' => 'email' ]); ``` Or if you extend the users table, the behavior is already loaded, so just configure it with: @@ -141,7 +145,7 @@ There are two custom messages (Auth.SocialLoginFailure.messages) and one default To use a custom component to handle the login, do: ```php Configure::write('Auth.SocialLoginFailure.component', 'MyLoginA'); -``` +``` The default configuration is: ```php @@ -167,4 +171,4 @@ The default configuration is: ... ] ] -``` +``` From 7bb8eff63b9bef5138bd1ff0dd7d06c4dd9519d1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 21 Oct 2021 08:50:40 -0300 Subject: [PATCH 634/685] Set theme jekyll-theme-slate --- _config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 _config.yml diff --git a/_config.yml b/_config.yml new file mode 100644 index 000000000..c74188174 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-slate \ No newline at end of file From 91b41b58d2d439dc08b1432819cae8f49f4a4906 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 21 Oct 2021 08:51:05 -0300 Subject: [PATCH 635/685] Set theme jekyll-theme-cayman --- _config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_config.yml b/_config.yml index c74188174..c4192631f 100644 --- a/_config.yml +++ b/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-slate \ No newline at end of file +theme: jekyll-theme-cayman \ No newline at end of file From 80a93a845c157070f7c5f01bde7060acfda063ef Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 21 Oct 2021 18:05:58 -0300 Subject: [PATCH 636/685] Improved docs for 2fa with disable|enable block. Add link to 2fa and info about enable|disable authentication component and authorization component --- .../Documentation/Two-Factor-Authenticator.md | 36 ++++++++++++++----- Docs/Documentation/Yubico-U2F.md | 26 +++++++++----- Docs/Home.md | 31 ++++++++++++++++ 3 files changed, 75 insertions(+), 18 deletions(-) diff --git a/Docs/Documentation/Two-Factor-Authenticator.md b/Docs/Documentation/Two-Factor-Authenticator.md index 0ee975fc8..022445a01 100644 --- a/Docs/Documentation/Two-Factor-Authenticator.md +++ b/Docs/Documentation/Two-Factor-Authenticator.md @@ -1,28 +1,46 @@ Two Factor Authenticator =============================== +The plugin offers an easy way to integrate OTP Two-Factor authentication +in the users login flow of your application. -Installation ------------- -To enable this feature you need to + +Installation Requirement +------------------------ +Before you enable the feature you need to run ``` composer require robthree/twofactorauth ``` -Setup ------ +By default the feature is disabled. + +Enabling +-------- -Enable one-time password authenticator in your bootstrap.php file: +First install robthree/twofactorauth using composer: -Config/bootstrap.php ``` -Configure::write('OneTimePasswordAuthenticator.login', true); +composer require robthree/twofactorauth +``` + +Then add this in your config/users.php file: + +```php + 'OneTimePasswordAuthenticator.login' => true, +``` + +Disabling +--------- +You can disable it by adding this in your config/users.php file: + +```php + 'OneTimePasswordAuthenticator.login' => false, ``` 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 +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). diff --git a/Docs/Documentation/Yubico-U2F.md b/Docs/Documentation/Yubico-U2F.md index bf398013b..73511f16c 100644 --- a/Docs/Documentation/Yubico-U2F.md +++ b/Docs/Documentation/Yubico-U2F.md @@ -1,22 +1,30 @@ YubicoKey U2F ============= -Installation ------------- -To enable this feature you need to +The plugin offers an easy way to integrate U2F in the users login flow +of your application. + +Enabling +-------- + +First install yubico/u2flib-server using composer: ``` composer require yubico/u2flib-server:^1.0 ``` -Setup ------ - -Enable it in your bootstrap.php file: +Then add this in your config/users.php file: -Config/bootstrap.php +```php + 'U2f.enabled' => true, ``` -Configure::write('U2f.enabled', true); + +Disabling +--------- +You can disable it by adding this in your config/users.php file: + +```php + 'U2f.enabled' => false, ``` How does it work diff --git a/Docs/Home.md b/Docs/Home.md index b5a151f0b..ad8e45ff0 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -90,6 +90,37 @@ I want to ``` * [social login](./Documentation/SocialAuthentication.md#setup) + * [OTP Two-factor authenticator](./Documentation/Two-Factor-Authenticator.md) + * [Yubico Key U2F Two-factor authenticator](./Documentation/Yubico-U2F.md) + * +
+ Authentication component + Add this to your config/users.php file to autoload the component (default): + + ```php + 'Auth.AuthenticationComponent.load' => true, + ``` + + To not autoload add this to your config/users.php + + ```php + 'Auth.AuthenticationComponent.load' => false, + ``` +
+ *
+ Authorization component + Add this to your config/users.php file to autoload the component (default): + + ```php + 'Auth.AuthorizationComponent.enabled' => true, + ``` + + To not autoload add this to your config/users.php + + ```php + 'Auth.AuthorizationComponent.enabled' => false, + ``` +
Migration guides ---------------- From 91842587a14ffc5b12e9e1cba154737ed4991e2e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 21 Oct 2021 18:19:10 -0300 Subject: [PATCH 637/685] Fixing indentation to correct display markups --- Docs/Home.md | 90 ++++++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/Docs/Home.md b/Docs/Home.md index ad8e45ff0..a6ca5c092 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -37,9 +37,10 @@ I want to * enable or disable *
email validation + Add this to your config/users.php file to disable email validation - ```php + ```php 'Users.Email.validate' => false, ``` or this to enable (default) @@ -49,66 +50,71 @@ I want to ```
*
- registration - Add this to your config/users.php file to disable registration + registration - ```php - 'Users.Registration.active' => false, - ``` + Add this to your config/users.php file to disable registration + + ```php + 'Users.Registration.active' => false, + ``` or this to enable (default) - ```php - 'Users.Registration.active' => true, - ``` + ```php + 'Users.Registration.active' => true, + ```
*
- reCaptcha on registration - To enable reCaptcha you need to register your site at google reCaptcha console - and add this to your config/users.php file to enable on registration: - - ```php - 'Users.reCaptcha.registration' => true, - ``` - To disable (default) add this to your config/users.php - - ```php - 'Users.reCaptcha.registration' => false, - ``` + reCaptcha on registration + + To enable reCaptcha you need to register your site at google reCaptcha console + and add this to your config/users.php file to enable on registration: + + ```php + 'Users.reCaptcha.registration' => true, + ``` + To disable (default) add this to your config/users.php + + ```php + 'Users.reCaptcha.registration' => false, + ```
*
- reCaptcha on login - To enable reCaptcha you need to register your site at google reCaptcha console - and add this to your config/users.php file to enable on login: - - ```php - 'Users.reCaptcha.login' => true, - ``` - To disable (default) add this to your config/users.php - - ```php - 'Users.reCaptcha.login' => false, - ``` + reCaptcha on login + + To enable reCaptcha you need to register your site at google reCaptcha console + and add this to your config/users.php file to enable on login: + + ```php + 'Users.reCaptcha.login' => true, + ``` + To disable (default) add this to your config/users.php + + ```php + 'Users.reCaptcha.login' => false, + ```
* [social login](./Documentation/SocialAuthentication.md#setup) * [OTP Two-factor authenticator](./Documentation/Two-Factor-Authenticator.md) * [Yubico Key U2F Two-factor authenticator](./Documentation/Yubico-U2F.md) *
- Authentication component - Add this to your config/users.php file to autoload the component (default): + Authentication component + + Add this to your config/users.php file to autoload the component (default): - ```php - 'Auth.AuthenticationComponent.load' => true, - ``` + ```php + 'Auth.AuthenticationComponent.load' => true, + ``` - To not autoload add this to your config/users.php + To not autoload add this to your config/users.php - ```php - 'Auth.AuthenticationComponent.load' => false, - ``` + ```php + 'Auth.AuthenticationComponent.load' => false, + ```
*
Authorization component + Add this to your config/users.php file to autoload the component (default): ```php From 93bb7e403117ea3229c3b8042fe61e00ba48160a Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 21 Oct 2021 18:33:25 -0300 Subject: [PATCH 638/685] Added info about TOS validation and Remember me --- Docs/Home.md | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/Docs/Home.md b/Docs/Home.md index a6ca5c092..dbf128ee0 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -96,8 +96,7 @@ I want to * [social login](./Documentation/SocialAuthentication.md#setup) * [OTP Two-factor authenticator](./Documentation/Two-Factor-Authenticator.md) * [Yubico Key U2F Two-factor authenticator](./Documentation/Yubico-U2F.md) - * -
+ *
Authentication component Add this to your config/users.php file to autoload the component (default): @@ -128,6 +127,38 @@ I want to ```
+ *
+ TOS validation + + Add this to your config/users.php file to enable (default): + + ```php + 'Users.Tos.required' => true, + ``` + + To disable add this to your config/users.php + + ```php + 'Users.Tos.required' => false, + ``` +
+ + *
+ remember me + + Add this to your config/users.php file to enable (default): + + ```php + 'Users.RememberMe.active' => true, + ``` + + To disable add this to your config/users.php + + ```php + 'Users.RememberMe.active' => false, + ``` +
+ Migration guides ---------------- From 46750ebfd2d0434d1bad5823e4f8466a488cfb1f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 24 Oct 2021 10:18:01 -0300 Subject: [PATCH 639/685] Added permissions doc --- Docs/Documentation/Permissions.md | 183 ++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 Docs/Documentation/Permissions.md diff --git a/Docs/Documentation/Permissions.md b/Docs/Documentation/Permissions.md new file mode 100644 index 000000000..077bbe9d8 --- /dev/null +++ b/Docs/Documentation/Permissions.md @@ -0,0 +1,183 @@ +Permissions +=========== +The plugin is setup to perform permissions check for all requests using +Superuser and Rbac policies. + +Superuser policy allow the superuser to access any page. + +The Rbac policy allows you to define a list of rules at config/permissions.php +to perform checks based on request information (prefix, plugin, controller, action, etc) +and user data. + +You can find the the permission rule syntax at [CakeDC/auth documentation.](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/Rbac.md#permission-rules-syntax) + +I want to allow access to public actions (non-logged user) +---------------------------------------------------------- +To allow access to public actions (that does not requires a looged) we need to include a new rule at config/permissions.php +using the 'bypassAuth' key. + +```php + [ + //...... all other rules + [ + 'controller' => 'Pages', + 'action' => ['home', 'contact', 'projects'] + 'bypassAuth' => true, + ], + ], +]; +``` + +I want to allow access to one specific action +--------------------------------------------- +To allow access to specific action we need to include a new rule at config/permissions.php + +- Path: /{controler}/{action} +```php + [ + //...... all other rules + [ + //Allow user, manager and author roles to access /books + 'role' => ['user', 'manager', 'author'], + 'controller' => 'Books', + 'action' => 'index', + ], + [ + //Allow user to access /dashboard/home + 'role' => 'user', + 'controller' => 'Dashbord', + 'action' => 'home', + ], + [ + //Allow user to access /articles, /articles/add and /article/edit + 'role' => ['manager'], + 'controller' => 'Articles', + 'action' => ['index', 'add', 'edit'], + ], + ], +]; +``` + +- Path: /{plugin}/{prefix}/{controler}/{action} +```php + [ + //...... all other rules + [ + //Allow user to access /reports/admin/categories + 'plugin' => 'Reports', + 'prefix' => 'Admin', + 'role' => ['manager'], + 'controller' => 'Categories', + 'action' => ['index'], + ], + ], +]; +``` + +I want to allow access to all actions from one controller +--------------------------------------------------------- +To allow access to specific all actions from one controller we need to include a new rule at config/permissions.php +using the value '*' for 'action' key. + +```php + [ + //...... all other rules + [ + //Allow user, manager and author roles to access any action from books controller + 'role' => ['user', 'manager', 'author'], + 'controller' => 'Books', + 'action' => '*', + ], + ] +]; +``` + +I want to allow access to all from one prefix +--------------------------------------------- +To allow access to specific to all pages from one prefix we need to include a new rule at config/permissions.php +using the value '*' for 'plugin', 'controller' and 'action' keys. + +```php + [ + //...... all other rules + [ + //Allow user, manager and author roles to access any action from books controller + 'role' => ['user', 'manager', 'author'], + 'plugin' => '*', + 'prefix' => 'Admin', + 'controller' => '*', + 'action' => '*', + ], + ], +]; +``` + +I want to allow access to entity owned by the user +-------------------------------------------------- +To allow access to entity owned by the user we need to include a new rule +at config/permissions.php using the 'allowed' key. + +```php + [ + //...... all other rules + [ + // + 'role' => 'user', + 'controller' => 'Articles', + 'action' => ['edit'] + 'allowed' => new \CakeDC\Auth\Rbac\Rules\Owner([ + 'table' => 'Articles', + 'id' => 'id', + 'ownerForeignKey' => 'owner_id' + ]), + ], + ], +]; +``` + +[For more information check owner rule documentation](https://github.com/CakeDC/auth/blob/6.next-cake4/Docs/Documentation/OwnerRule.md) + + +I want to allow access to action using a custom logic +---------------------------------------------------- +Permission rule can have a custom callback. Adde the rule at config/permissions.php using the 'allowed' key. + +```php + [ + //...... all other rules + [ + // + 'role' => 'user', + 'controller' => 'Posts', + 'action' => ['edit'] + 'allowed' => function (array $user, $role, \Cake\Http\ServerRequest $request) { + $postId = \Cake\Utility\Hash::get($request->params, 'pass.0'); + $post = \Cake\ORM\TableRegistry::get('Posts')->get($postId); + $userId = $user['id']; + if (!empty($post->user_id) && !empty($userId)) { + return $post->user_id === $userId; + } + return false; + } + ], + ], +]; +``` + +[For more information check CakeDC/Auth documentation](https://github.com/CakeDC/auth/blob/6.next-cake4/Docs/Documentation/Rbac.md#permission-callbacks) + + From 7e4f3832a437a1f146a1cdcdd3b355b2681bb2b1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 24 Oct 2021 10:26:49 -0300 Subject: [PATCH 640/685] Added permissions doc --- Docs/Documentation/Permissions.md | 4 ++-- Docs/Home.md | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Docs/Documentation/Permissions.md b/Docs/Documentation/Permissions.md index 077bbe9d8..d2b55f20f 100644 --- a/Docs/Documentation/Permissions.md +++ b/Docs/Documentation/Permissions.md @@ -9,7 +9,7 @@ The Rbac policy allows you to define a list of rules at config/permissions.php to perform checks based on request information (prefix, plugin, controller, action, etc) and user data. -You can find the the permission rule syntax at [CakeDC/auth documentation.](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/Rbac.md#permission-rules-syntax) +You can find the permission rule syntax at [CakeDC/auth documentation.](https://github.com/CakeDC/auth/blob/master/Docs/Documentation/Rbac.md#permission-rules-syntax) I want to allow access to public actions (non-logged user) ---------------------------------------------------------- @@ -100,7 +100,7 @@ return [ ]; ``` -I want to allow access to all from one prefix +I want to allow access to all controllers from one prefix --------------------------------------------- To allow access to specific to all pages from one prefix we need to include a new rule at config/permissions.php using the value '*' for 'plugin', 'controller' and 'action' keys. diff --git a/Docs/Home.md b/Docs/Home.md index dbf128ee0..a78a20cf1 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -159,6 +159,12 @@ I want to ```
+- allow access to + - [public actions (non-logged user)](./Documentation/Permissions.md#i-want-to-allow-access-to-public-actions-non-logged-user) + - [one specific action](./Documentation/Permissions.md#i-want-to-allow-access-to-one-specific-action) + - [all actions from one controller](./Documentation/Permissions.md#i-want-to-allow-access-to-all-actions-from-one-controller) + - [all controllers from one prefix](./Documentation/Permissions.md#i-want-to-allow-access-to-all-controllers-from-one-prefix) + Migration guides ---------------- From 497a2589ed80b2586ec34851cb65c99c7a83a29f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Sun, 24 Oct 2021 10:30:39 -0300 Subject: [PATCH 641/685] Added permissions doc --- Docs/Home.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Docs/Home.md b/Docs/Home.md index a78a20cf1..8686caef1 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -164,6 +164,8 @@ I want to - [one specific action](./Documentation/Permissions.md#i-want-to-allow-access-to-one-specific-action) - [all actions from one controller](./Documentation/Permissions.md#i-want-to-allow-access-to-all-actions-from-one-controller) - [all controllers from one prefix](./Documentation/Permissions.md#i-want-to-allow-access-to-all-controllers-from-one-prefix) + - [entity owned by the user](./Documentation/Permissions.md#i-want-to-allow-access-to-entity-owned-by-the-user) + - [action using a custom logic](./Documentation/Permissions.md#i-want-to-allow-access-to-action-using-a-custom-logic) Migration guides ---------------- From 70d073f91b44ffa7b286ed711dbb44351186abf6 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 27 Oct 2021 12:27:10 -0300 Subject: [PATCH 642/685] Added section 'I want to customize my login page to' --- Docs/Home.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/Docs/Home.md b/Docs/Home.md index 8686caef1..70a0bbc5c 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -70,6 +70,8 @@ I want to and add this to your config/users.php file to enable on registration: ```php + 'Users.reCaptcha.key' => 'YOUR RECAPTCHA KEY', + 'Users.reCaptcha.secret' => 'YOUR RECAPTCHA SECRET', 'Users.reCaptcha.registration' => true, ``` To disable (default) add this to your config/users.php @@ -85,6 +87,8 @@ I want to and add this to your config/users.php file to enable on login: ```php + 'Users.reCaptcha.key' => 'YOUR RECAPTCHA KEY', + 'Users.reCaptcha.secret' => 'YOUR RECAPTCHA SECRET', 'Users.reCaptcha.login' => true, ``` To disable (default) add this to your config/users.php @@ -167,6 +171,57 @@ I want to - [entity owned by the user](./Documentation/Permissions.md#i-want-to-allow-access-to-entity-owned-by-the-user) - [action using a custom logic](./Documentation/Permissions.md#i-want-to-allow-access-to-action-using-a-custom-logic) +- customize my login page to + -
+ use my template + Copy the login file from `{project_dir}/vendor/cakedc/users/templates/Users/` + to `{project_dir}/templates/plugin/CakeDC/Users/Users`. +
+ + -
+ use a custom finder + First add this to your config/users.php: + + ``` + 'Auth.Identifiers.Password.resolver.finder' => 'myFinderName', + 'Auth.Identifiers.Social.authFinder' => 'myFinderName', + 'Auth.Identifiers.Token.resolver.finder' => 'myFinderName', + ``` + Important: You must have extended the model, see how to at [Extending the Plugin](Documentation/Extending-the-Plugin.md) +
+ + -
+ use a custom redirect url + To use a custom redirect url on login add this to your config/users.php: + + ``` + 'Auth.AuthenticationComponent.loginRedirect' => '/some/url/', + ``` + or + ``` + 'Auth.AuthenticationComponent.loginRedirect' => ['plugin' => false, 'controller' => 'Example', 'action' => 'home'], + ``` + Important: when using array you should pass `'plugin' => false,` to match your app controller. +
+ + -
+ enable|disable reCaptcha + + To enable reCaptcha you need to register your site at google reCaptcha console + and add this to your config/users.php file to enable on login: + + ```php + 'Users.reCaptcha.login' => true, + 'Users.reCaptcha.key' => 'YOUR RECAPTCHA KEY', + 'Users.reCaptcha.secret' => 'YOUR RECAPTCHA SECRET', + ``` + To disable (default) add this to your config/users.php + ```php + 'Users.reCaptcha.login' => false, + ``` +
+ + Migration guides ---------------- From 6010bc31ba7207bbf067cfa6a4aa239946c585c0 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 10:18:53 -0300 Subject: [PATCH 643/685] Improving events doc --- Docs/Documentation/Events.md | 205 +++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md index eedf5965d..3ac1e3b4b 100644 --- a/Docs/Documentation/Events.md +++ b/Docs/Documentation/Events.md @@ -48,3 +48,208 @@ EventManager::instance()->on( } ); ``` + +I want to add custom logic before user logout +--------------------------------------------- +When adding a custom logic to execute before user logout you +have access to user data and the controller object. The main logout +logic will be performed if you don't assign an array to result, but if +you set it we will use as redirect url. + +- Create or update file src/Event/UsersListener.php: +```php + 'beforeLogout', + ]; + } + + /** + * @param \Cake\Event\Event $event + */ + public function beforeLogout(\Cake\Event\Event $event) + { + $user = $event->getData('user'); + $controller = $event->getSubject(); + + //your custom logic + Cache::delete('dashboard_data_user_' . $user['id']); + $controller->Flash->succes(__('Some message if you want')); + + //If you want to ignore the logout logic you can, just set an url array as result to use as redirect + //$event->setResult(['plugin' => false, 'controller' => 'Page', 'action' => 'seeYouSoon']); + } +} +``` +- Add this at the end of your method Application::bootstrap if you have NOT done before. +```php +$this->getEventManager()->on(new \App\Event\UsersListener()); +``` + +I want to add custom logic before user register +--------------------------------------------- +When adding a custom logic to execute before user register you +have access to 'usersTable', 'userEntity' and 'options' keys in the event +object and the controller object. +You can also populate the new user entity or stop the register process. + +- Create or update file src/Event/UsersListener.php: +```php + 'beforeRegister', + ]; + } + + /** + * @param \Cake\Event\Event $event + */ + public function beforeRegister(\Cake\Event\Event $event) + { + $controller = $event->getSubject(); + $user = $event->getData('userEntity'); + $table = $event->getData('usersTable'); + $options = $event->getData('options'); + + //Or custom logic + $controller->Flash->succes(__('Some message if you want')); + + //When you set an entity as result a part of register logic is skipped (ex: reCaptcha) + $newUser = $table->newEntity([ + 'username' => 'forceEventRegister', + 'email' => 'eventregister@example.com', + 'password' => 'password', + 'active' => true, + 'tos' => true, + ]); + // + $event->setResult($newUser); + //If you want to stop registration use + //$event->stopPropagation(); + //$event->setResult(['plugin' => false, 'controller' => 'Somewhere', 'action' => 'toRedirect']); + } +} + +``` +- Add this at the end of your method Application::bootstrap if you have NOT done before. +```php +$this->getEventManager()->on(new \App\Event\UsersListener()); +``` + +I want to add custom logic before linking social account +-------------------------------------------------------- +When adding a custom logic to execute before linking social account you +have access to 'location' and 'request' keys in the event object and +the controller object. + +- Create or update file src/Event/UsersListener.php: +```php + 'beforeSocialLoginRedirect', + ]; + } + + /** + * @param \Cake\Event\Event $event + */ + public function beforeSocialLoginRedirect(\Cake\Event\Event $event) + { + $controller = $event->getSubject(); + $location = $event->getData('location'); + $request = $event->getData('request'); + + //your custom logic + } +} + +``` +- Add this at the end of your method Application::bootstrap if you have NOT done before. +```php +$this->getEventManager()->on(new \App\Event\UsersListener()); +``` + +I want to add custom logic before creating social account +--------------------------------------------------------- +When adding a custom logic to execute before creating social account you +have access to 'userEntity' and 'data' keys in the event object and +the social behavior object. + +You can also set a new user entity object as result. + +- Create or update file src/Event/UsersListener.php: +```php + 'beforeSocialLoginRedirect', + ]; + } + + /** + * @param \Cake\Event\Event $event + */ + public function beforeSocialLoginRedirect(\Cake\Event\Event $event) + { + $userEntity = $event->getData('userEntity'); + $socialData = $event->getData('data'); + + //your custom logic + + //If you want to use another entity use this + //$event->setResult($anotherUserEntity); + } +} +``` +- Add this at the end of your method Application::bootstrap if you have NOT done before. +```php +$this->getEventManager()->on(new \App\Event\UsersListener()); +``` From 3c2f06bfc57c73d008de3b7f15111c127a8f2f7e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 10:22:17 -0300 Subject: [PATCH 644/685] Improving events doc --- Docs/Home.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Docs/Home.md b/Docs/Home.md index 70a0bbc5c..b2b39cef9 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -221,6 +221,11 @@ I want to ```
+- add custom logic before + - [user logout](./Documentation/Events.md#i-want-to-add-custom-logic-before-user-logout) + - [user register](./Documentation/Events.md#i-want-to-add-custom-logic-before-user-register) + - [linking social account](./Documentation/Events.md#i-want-to-add-custom-logic-before-linking-social-account) + - [creating social account](./Documentation/Events.md#i-want-to-add-custom-logic-before-creating-social-account) Migration guides ---------------- From 5213747d69194de4019b079cfe15614edc1236b7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 10:58:31 -0300 Subject: [PATCH 645/685] Improving events doc (after events) --- Docs/Documentation/Events.md | 303 +++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md index 3ac1e3b4b..fb699c7af 100644 --- a/Docs/Documentation/Events.md +++ b/Docs/Documentation/Events.md @@ -253,3 +253,306 @@ class UsersListener implements EventListenerInterface ```php $this->getEventManager()->on(new \App\Event\UsersListener()); ``` + +I want to add custom logic after user login +------------------------------------------- +When adding a custom logic to execute after user login you +have access to user data. You can also set an array as result to +perform a custom redirect. + +- Create or update file src/Event/UsersListener.php: +```php + 'afterLogin', + ]; + } + + /** + * @param \Cake\Event\Event $event + */ + public function afterLogin(\Cake\Event\Event $event) + { + $user = $event->getData('user'); + //your custom logic + //$this->loadModel('SomeOptionalUserLogs')->newLogin($user); + + //If you want to use a custom redirect + $event->setResult([ + 'plugin' => false, + 'controller' => 'Dashboard', + 'action' => 'home', + ]); + } +} +``` +- Add this at the end of your method Application::bootstrap if you have NOT done before. +```php +$this->getEventManager()->on(new \App\Event\UsersListener()); +``` + +I want to add custom logic after user logout +--------------------------------------------- +When adding a custom logic to execute after user logout you +have access to user data and the controller object. You can also +set an array as result to perform a custom redirect. + +- Create or update file src/Event/UsersListener.php: +```php + 'afterLogout', + ]; + } + + /** + * @param \Cake\Event\Event $event + */ + public function afterLogout(\Cake\Event\Event $event) + { + $user = $event->getData('user'); + $controller = $event->getSubject(); + //your custom logic + + //If you want to use a custom redirect + $event->setResult([ + 'plugin' => false, + 'controller' => 'Pages', + 'action' => 'thankYou', + ]); + } +} + +``` +- Add this at the end of your method Application::bootstrap if you have NOT done before. +```php +$this->getEventManager()->on(new \App\Event\UsersListener()); +``` + +I want to add custom logic after user register +---------------------------------------------- +When adding a custom logic to execute after user register you +have access to user data and the controller object. You can also +set a custom http response as result to render a different content +or perform a custom redirect. + +- Create or update file src/Event/UsersListener.php: +```php + 'afterRegister', + ]; + } + + /** + * @param \Cake\Event\Event $event + */ + public function afterRegister(\Cake\Event\Event $event) + { + $user = $event->getData('user'); + $controller = $event->getSubject(); + //your custom logic + + //If you want to use a custom response to render a json. + $response = $controller->getResponse()->withStringBody(json_encode(['success' => true, 'id' => $user['id']])); + $event->setResult($response); + + //or if you want to use a custom redirect. + $response = $controller->getResponse()->withLocation("/some/page"); + $event->setResult($response); + } +} + +``` +- Add this at the end of your method Application::bootstrap if you have NOT done before. +```php +$this->getEventManager()->on(new \App\Event\UsersListener()); +``` + +I want to add custom logic after user changed the password +---------------------------------------------------------- +When adding a custom logic to execute after user change the password +you have access to some user data and the controller object. You can also +set an array as result to perform a custom redirect. + +- Create or update file src/Event/UsersListener.php: +```php + 'afterChangePassword', + ]; + } + + /** + * @param \Cake\Event\Event $event + */ + public function afterChangePassword(\Cake\Event\Event $event) + { + $user = $event->getData('user'); + $controller = $event->getSubject(); + //your custom logic + + //If you want to use a custom redirect + $event->setResult([ + 'plugin' => false, + 'controller' => 'Pages', + 'action' => 'infoPassword', + ]); + } +} + +``` +- Add this at the end of your method Application::bootstrap if you have NOT done before. +```php +$this->getEventManager()->on(new \App\Event\UsersListener()); +``` + + +I want to add custom logic after sending the token for user validation +---------------------------------------------------------------------- +When adding a custom logic to execute after sending the token for user +validation you can also set an array as result to perform a custom redirect. + +- Create or update file src/Event/UsersListener.php: +```php + 'afterResendTokenValidation', + ]; + } + + /** + * @param \Cake\Event\Event $event + */ + public function afterResendTokenValidation(\Cake\Event\Event $event) + { + $controller = $event->getSubject(); + //your custom logic + + //If you want to use a custom redirect + $event->setResult([ + 'plugin' => false, + 'controller' => 'Pages', + 'action' => 'infoValidation', + ]); + } +} + +``` +- Add this at the end of your method Application::bootstrap if you have NOT done before. +```php +$this->getEventManager()->on(new \App\Event\UsersListener()); +``` + +I want to add custom logic after user email is validated +-------------------------------------------------------- +When adding a custom logic to execute after user email is validate +you have access to some user data and the controller object. You can also +set an array as result to perform a custom redirect. + +- Create or update file src/Event/UsersListener.php: +```php + 'afterEmailTokenValidation', + ]; + } + + /** + * @param \Cake\Event\Event $event + */ + public function afterEmailTokenValidation(\Cake\Event\Event $event) + { + $user = $event->getData('user'); + $controller = $event->getSubject(); + //your custom logic + + //If you want to use a custom redirect + $event->setResult([ + 'plugin' => false, + 'controller' => 'Pages', + 'action' => 'infoPassword', + ]); + } +} + +``` +- Add this at the end of your method Application::bootstrap if you have NOT done before. +```php +$this->getEventManager()->on(new \App\Event\UsersListener()); +``` From 2d1d1bd15eca536b206495c3a6824bde0baf3f14 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 11:12:27 -0300 Subject: [PATCH 646/685] Improving events doc (after events) --- Docs/Documentation/Events.md | 76 ++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/Docs/Documentation/Events.md b/Docs/Documentation/Events.md index fb699c7af..61fcee79d 100644 --- a/Docs/Documentation/Events.md +++ b/Docs/Documentation/Events.md @@ -14,40 +14,8 @@ The events in this plugin follow these conventions `.eventManager()->on(Plugin::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'); - } - - -How to make an autologin using `EVENT_AFTER_EMAIL_TOKEN_VALIDATION` event - -```php -EventManager::instance()->on( - \CakeDC\Users\Plugin::EVENT_AFTER_EMAIL_TOKEN_VALIDATION, - function($event){ - $users = $this->getTableLocator()->get('Users'); - $user = $users->get($event->getData('user')->id); - $this->Authentication->setIdentity($user); - } -); -``` I want to add custom logic before user logout --------------------------------------------- @@ -556,3 +524,45 @@ class UsersListener implements EventListenerInterface ```php $this->getEventManager()->on(new \App\Event\UsersListener()); ``` + +I want to add custom logic after user email is validated to autologin user +-------------------------------------------------------------------------- +This is how you can autologin the user after email is validate: + +- Create or update file src/Event/UsersListener.php: +```php + 'afterEmailTokenValidation', + ]; + } + + /** + * @param \Cake\Event\Event $event + */ + public function afterEmailTokenValidation(\Cake\Event\Event $event) + { + $table = $this->loadModel('Users'); + $userData = $event->getData('user'); + $user = $table->get($userData['id']); + $this->Authentication->setIdentity($user); + } +} + +``` +- Add this at the end of your method Application::bootstrap if you have NOT done before. +```php +$this->getEventManager()->on(new \App\Event\UsersListener()); +``` From 93a4f56b77648de0904bfc1953c9898cfb8fca1c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 11:17:48 -0300 Subject: [PATCH 647/685] Improving events doc (after events) --- Docs/Home.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Docs/Home.md b/Docs/Home.md index b2b39cef9..fc90335d9 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -227,6 +227,16 @@ I want to - [linking social account](./Documentation/Events.md#i-want-to-add-custom-logic-before-linking-social-account) - [creating social account](./Documentation/Events.md#i-want-to-add-custom-logic-before-creating-social-account) +- add custom logic after + - [user login](./Documentation/Events.md#i-want-to-add-custom-logic-after-user-login) + - [user logout](./Documentation/Events.md#i-want-to-add-custom-logic-after-user-logout) + - [user register](./Documentation/Events.md#i-want-to-add-custom-logic-after-user-register) + - [user changed the password](./Documentation/Events.md#i-want-to-add-custom-logic-after-user-changed-the-password) + - [sending the token for user validation](./Documentation/Events.md#i-want-to-add-custom-logic-after-sending-the-token-for-user-validation) + - [user email is validated](./Documentation/Events.md#i-want-to-add-custom-logic-after-user-email-is-validated) + - [user email is validated to autologin user](./Documentation/Events.md#i-want-to-add-custom-logic-after-user-email-is-validated-to-autologin-user) + + Migration guides ---------------- From 3594702ea7f05079fa6a7d139e961a39591e449c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 12:19:45 -0300 Subject: [PATCH 648/685] Added section 'Creating config files' and don't use Configure::write --- Docs/Documentation/Installation.md | 48 ++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 4171bee7c..a9e14dbf5 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -2,7 +2,7 @@ Installation ============ Composer ------- +-------- ``` composer require cakedc/users @@ -21,10 +21,6 @@ composer require league/oauth1-client:@stable NOTE: you'll need to enable social login 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... ``` @@ -47,7 +43,7 @@ Configure::write('OneTimePasswordAuthenticator.login', true); ``` Load the Plugin ------------ +--------------- Ensure the Users Plugin is loaded in your src/Application.php file @@ -65,6 +61,33 @@ Ensure the Users Plugin is loaded in your src/Application.php file } ``` + +Creating config files +--------------------- +You need to create the file config/users.php to configure the plugin. This documentation +assumes that you will create this file. + +Example config/users.php + +```php + true, +]; +``` + +***The plugin loads authentication and authorization plugins by default, +to be able to access your pages you NEED to have defined rules at the +file config/permissions.php. +You can copy the one from the plugin and add your permissions rules.*** + +```shell +cd {project_dir} +cp vendor/cakedc/users/config/permissions.php config/permissions.php +``` +[Go to permission documentation for more information.](./Documentation/Permissions.md) + + Creating Required Tables ------------------------ If you want to use the Users tables to store your users and social accounts: @@ -84,18 +107,19 @@ bin/cake users addSuperuser ``` Customization ----------- +------------- -Application::bootstrap +First, make sure to set the config `Users.config` at Application::bootstrap ``` $this->addPlugin(\CakeDC\Users\Plugin::class); Configure::write('Users.config', ['users']); -Configure::write('Users.Social.login', true); //to enable social login ``` -If you want to use social login, then in your config/users.php -``` +And update your config/users.php file, for example if you want to use social login: +```php + true, 'OAuth.providers.facebook.options.clientId' => 'YOUR APP ID', 'OAuth.providers.facebook.options.clientSecret' => 'YOUR APP SECRET', 'OAuth.providers.twitter.options.clientId' => 'YOUR APP ID', @@ -103,7 +127,7 @@ return [ //etc ]; ``` -IMPORTANT: Remember you'll need to configure your social login application **callback url** to use the provider specific endpoint, for example: +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` From f03e9f41853fbe57f242a9437f1025ed7e7df511 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 12:27:10 -0300 Subject: [PATCH 649/685] Added section 'Creating config files' and don't use Configure::write --- Docs/Documentation/Installation.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index a9e14dbf5..63c2584e5 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -61,6 +61,9 @@ Ensure the Users Plugin is loaded in your src/Application.php file } ``` +**Important note: The plugin loads authentication and authorization plugin and +uses RequestAuthorizationMiddleware with Rbac|Superuser policy you +should not load then manually** Creating config files --------------------- From c0e4a55542ac91eb9e17a0977601b40bb6a22cfe Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 13:13:00 -0300 Subject: [PATCH 650/685] Mention config/users.php instead of Configure::write --- Docs/Documentation/Authentication.md | 60 +++++++++++----------- Docs/Documentation/Extending-the-Plugin.md | 11 ++-- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 304d8e4dc..74d2c3c1f 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -2,15 +2,15 @@ Authentication ============== This plugin uses the new authentication plugin [cakephp/authentication](https://github.com/cakephp/authentication/) instead of CakePHP Authentication component, but don't worry, the default configuration should be enough for your -projects. +projects. We've tried to simplify configuration as much as possible using defaults, but keep the ability to override them when needed. Authentication Component ------------------------ -The default behavior is to load the authentication component at UsersController, -defining the default urls for loginAction, loginRedirect, logoutRedirect but not requiring +The default behavior is to load the authentication component at UsersController, +defining the default urls for loginAction, loginRedirect, logoutRedirect but not requiring the request to have a identity. If you prefer to load the component yourself you can set 'Auth.AuthenticationComponent.load': @@ -29,7 +29,7 @@ $user = $this->Authentication->getIdentity()->getOriginalData(); ``` The default configuration for Auth.AuthenticationComponent is: -``` +```php [ 'load' => true, 'loginRedirect' => '/', @@ -57,25 +57,23 @@ list of authenticators includes: These authenticators should be enough for your application, but you easily customize it setting the Auth.Authenticators config key. - -For example if you add JWT authenticator you can set: -``` -$authenticators = Configure::read('Auth.Authenticators'); -$authenticators['Jwt'] = [ - 'className' => 'Authentication.Jwt', +For example if you add JWT authenticator you must add this to your config/users.php file: + +```php +'Auth.Authenticators.Jwt' => [ 'queryParam' => 'token', 'skipTwoFactorVerify' => true, -]; -Configure::write('Auth.Authenticators', $authenticators); + 'className' => 'Authentication.Jwt', +], +``` -``` **You may have noticed the 'skipTwoFactorVerify' option, this option is used to identify if a authenticator should skip the two factor flow** The authenticators are loaded by \CakeDC\Users\Loader\AuthenticationServiceLoader class at load authentication service method from plugin object. - + See the full Auth.Authenticators at config/users.php Identifiers @@ -86,11 +84,12 @@ The identifies are defined to work correctly with the default authenticators, we - CakeDC/Users.Social, for Social and SocialPendingEmail authenticators - Authentication.Token, for TokenAuthenticator -As you add more authenticators you may need to add identifiers, please check identifiers available at +As you add more authenticators you may need to add identifiers, please check identifiers available at [official documentation](https://github.com/cakephp/authentication/blob/master/docs/Identifiers.md) The default value for Auth.Identifiers is: -``` + +```php [ 'Password' => [ 'className' => 'Authentication.Password', @@ -127,14 +126,15 @@ For both form login and social login we use a base component 'CakeDC/Users.Login it check the result of authentication service to redirect user to a internal page or show an authentication error. It provide some error messages for specific authentication result status, please check the config/users.php file. -To use a custom component to handle the login you could do: +To use a custom component to handle the login you should update your config/users.php file with: + +```php +'Auth.SocialLoginFailure.component' => 'MyLoginA', +'Auth.FormLoginFailure.component' => 'MyLoginB', ``` -Configure::write('Auth.SocialLoginFailure.component', 'MyLoginA'); -Configure::write('Auth.FormLoginFailure.component', 'MyLoginB'); -``` The default configuration are: -``` +```php [ ... 'Auth' => [ @@ -165,24 +165,24 @@ The default configuration are: ... ] ] -``` +``` -Authentication Service Loader +Authentication Service Loader ----------------------------- To make the integration with cakephp/authentication easier we load the authenticators and identifiers defined at Auth configuration and other components to work with social provider, two-factor authentication. -If the configuration is not enough for your project you may create a custom loader extending the +If the configuration is not enough for your project you may create a custom loader extending the default provided. - Create file src/Loader/AppAuthenticationServiceLoader.php -``` +```php \App\Loader\AuthenticationServiceLoader::class, ``` diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index e205ac8df..e06f8783c 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -123,7 +123,7 @@ class MyUsersController extends AppController { use LoginTrait; use RegisterTrait; - + /** * Initialize * @@ -212,7 +212,7 @@ https://book.cakephp.org/4/en/plugins.html#overriding-plugin-templates-from-insi Updating the Emails ------------------- -Extend the `\CakeDC\Users\Mailer\UsersMailer` class and override the email configuration to change the way the +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 @@ -236,8 +236,11 @@ class MyUsersMailer extends UsersMailer } } ``` -* Configure the Plugin to use this new mailer class in bootstrap or users.php -`Configure::write('Users.Email.mailerClass', \App\Mailer\MyUsersMailer::class);` +* Configure the plugin to use this new mailer class, add this in your config/users.php file: + +```php + 'Users.Email.mailerClass' => \App\Mailer\MyUsersMailer::class, +``` * Create the file `templates/email/text/custom_template_in_app_namespace.php` with your custom contents. Note you can also prepare an html version of the file, From c44869e53592ea2b99ebb5ffc9f54879da030d29 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 13:26:37 -0300 Subject: [PATCH 651/685] Mention config/users.php instead of Configure::write --- Docs/Documentation/Authorization.md | 36 ++++++++++++---------- Docs/Documentation/Installation.md | 6 ++-- Docs/Documentation/SocialAuthentication.md | 25 +++++++-------- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/Docs/Documentation/Authorization.md b/Docs/Documentation/Authorization.md index 992ffb183..58809f524 100644 --- a/Docs/Documentation/Authorization.md +++ b/Docs/Documentation/Authorization.md @@ -6,22 +6,25 @@ projects. We tried to allow you to start quickly without the need to configure a allow you to configure as much as possible. -If you don't want the plugin to autoload setup authorization, you can do: -``` -Configure::write('Auth.Authorization.enabled', false); +If you don't want the plugin to autoload setup authorization, you can disable +in your config/users.php with: + +```php +'Auth.Authorization.enabled' => false, ``` Authorization Middleware ------------------------ We load the RequestAuthorization and Authorization middleware with OrmResolver and RbacProvider(work with RequestAuthorizationMiddleware). -The middleware accepts some additional configurations, you can do: -``` -Configure::write('Auth.AuthorizationMiddleware', $config); +The middleware accepts some additional configurations, you can update in your +config/users.php file: +```php +'Auth.AuthorizationMiddleware' => $config, ``` The default configuration for authorization middleware is: -``` +```php [ 'unauthorizedHandler' => [ 'className' => 'CakeDC/Users.DefaultRedirect', @@ -41,7 +44,7 @@ The `CakeDC/Users.DefaultRedirect` offers additional behavior and config: You could do the following to set a custom url and flash message: -``` +```php [ 'unauthorizedHandler' => [ 'className' => 'CakeDC/Users.DefaultRedirect', @@ -61,7 +64,7 @@ You could do the following to set a custom url and flash message: ], ``` OR -``` +```php [ 'unauthorizedHandler' => [ 'className' => 'CakeDC/Users.DefaultRedirect', @@ -82,9 +85,10 @@ OR Authorization Component ----------------------- We autoload the authorization component at users controller using the default configuration, -if you don't want the plugin to autoload it, you can do: -``` -Configure::write('Auth.AuthorizationComponent.enabled', false); +if you don't want the plugin to autoload it, you can add this to your config/users.php file: + +```php +'Auth.AuthorizationComponent.enabled' => false, ``` You can check the configuration options available for authorization component at the @@ -100,7 +104,7 @@ default provided. - Create file src/Loader/AppAuthorizationServiceLoader.php -``` +```php \App\Loader\AppAuthorizationServiceLoader::class, ``` diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 63c2584e5..33a333c07 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -36,10 +36,10 @@ If you want to use Google Authenticator features... composer require robthree/twofactorauth:"^1.5.2" ``` -NOTE: you'll need to enable `OneTimePasswordAuthenticator.login` +NOTE: you'll need to enable `OneTimePasswordAuthenticator.login` in your config/users.php file: -``` -Configure::write('OneTimePasswordAuthenticator.login', true); +```php +'OneTimePasswordAuthenticator.login' => true, ``` Load the Plugin diff --git a/Docs/Documentation/SocialAuthentication.md b/Docs/Documentation/SocialAuthentication.md index 4c79c4a2b..f74b36e7a 100644 --- a/Docs/Documentation/SocialAuthentication.md +++ b/Docs/Documentation/SocialAuthentication.md @@ -32,21 +32,20 @@ Facebook/Twitter applications you want to use and update your file config/users. Check optional configs at [config/users.php](./../../config/users.php) inside 'OAuth' key -You can also change the default settings for social authenticate: +You can also change the default settings for social authenticate in your config/users.php file: ```php -Configure::write('Users', [ - 'Email' => [ + 'Users.Email' => [ //determines if the user should include email 'required' => true, //determines if registration workflow includes email validation 'validate' => true, ], - 'Social' => [ + 'Users.Social' => [ //enable social login 'login' => false, ], - 'Key' => [ + 'Users.Key' => [ 'Session' => [ //session key to store the social auth data 'social' => 'Users.social', @@ -60,7 +59,6 @@ Configure::write('Users', [ '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). @@ -70,7 +68,7 @@ In most situations you would not need to change any Oauth setting besides applic For new facebook aps you must use the graphApiVersion 2.8 or greater: ```php -Configure::write('OAuth.providers.facebook.options.graphApiVersion', 'v2.8'); +'OAuth.providers.facebook.options.graphApiVersion' => 'v2.8', ``` User Helper @@ -126,12 +124,11 @@ Social Indentifier ------------------ The social identifier "CakeDC/Users.Social", works with data provider by both social authenticator, it is responsible of finding or creating a user registry for the social user data request. -By default it'll fetch user data with finder 'all', but you can use a custom one. Add this to your -Application class, after CakeDC/Users Plugin is loaded. +By default, it'll fetch user data with finder 'all', but you can use a custom one. Add this to your +config/users.php: + ```php - $identifiers = Configure::read('Auth.Identifiers'); - $identifiers['CakeDC/Users.Social']['authFinder'] = 'customSocialAuth'; - Configure::write('Auth.Identifiers', $identifiers); +'Auth.Identifiers.Social.authFinder' => 'customSocialAuth', ``` @@ -142,9 +139,9 @@ service to redirects user to an internal page or show an authentication error. I There are two custom messages (Auth.SocialLoginFailure.messages) and one default message (Auth.SocialLoginFailure.defaultMessage). -To use a custom component to handle the login, do: +To use a custom component to handle the login add this to your config/users.php file: ```php -Configure::write('Auth.SocialLoginFailure.component', 'MyLoginA'); +'Auth.SocialLoginFailure.component' => 'MyLoginA', ``` The default configuration is: From 042376f57434b5e5c47be5daa0528cb711d613d4 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 13:39:34 -0300 Subject: [PATCH 652/685] Mention config/users.php instead of Configure::write --- Docs/Documentation/Configuration.md | 60 ++++++++++++++--------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index dea40fd4d..080adb67f 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -6,12 +6,11 @@ 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 +Make sure you loaded the plugin and is using a custom config/users.php file at Application::bootstrap ``` // The following configuration setting must be set before loading the Users plugin +$this->addPlugin(\CakeDC\Users\Plugin::class); 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 @@ -28,13 +27,14 @@ $ 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'); +And update your config/users.php file: -Configure::write('OAuth.providers.twitter.options.clientId', 'YOUR APP ID'); -Configure::write('OAuth.providers.twitter.options.clientSecret', 'YOUR APP SECRET'); +```php +'Users.Social.login' => true, +'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', ``` Or use the config override option when loading the plugin (see above) @@ -44,15 +44,18 @@ 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** +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 +To enable reCaptcha you need to register your site at google reCaptcha console +and add this to your config/users.php file: + +```php +'Users.reCaptcha.key' => 'YOUR RECAPTCHA KEY', +'Users.reCaptcha.secret' => 'YOUR RECAPTCHA SECRET', +'Users.reCaptcha.registration' => true, //enable on registration +'Users.reCaptcha.login' => true, //enable on login ``` @@ -70,10 +73,11 @@ and [cakephp/authorization](https://github.com/cakephp/authorization) plugins we into their documentation for more information. Most authentication/authorization configuration is defined at 'Auth' key, for example -if you don't want the plugin to autoload the authorization service, you could do: +if you don't want the plugin to autoload the authorization service, you could add this +to your config/users.php file: ``` -Configure::write('Auth.Authorization.enable', false) +'Auth.Authorization.enable' => false, ``` Interesting Users options and defaults @@ -161,25 +165,17 @@ To learn more about it please check the configurations for [Authentication](Auth You need to configure 2 things (version 9.0.4): -* Change the Password identifier fields and the Authenticator for Forms configuration to let it use the email instead of the username for user identify. Add this to your Application class, right before CakeDC/Users Plugin is loaded. +* Change the Password identifier fields and the Authenticator for Forms +configuration to let it use the email instead of the username for +user identify. Add this to your config/users.php: ```php - // Load more plugins here - $identifiers = Configure::read('Auth.Identifiers'); - $identifiers['Password']['fields']['username'] = 'email'; - Configure::write('Auth.Identifiers', $identifiers); - - $authenticators = Configure::read('Auth.Authenticators'); - $authenticators['Form']['fields']['username'] = 'email'; - Configure::write('Auth.Authenticators', $authenticators); - - //Configure::write('Users.config', ['users', 'permissions']); - - $this->addPlugin(\CakeDC\Users\Plugin::class); +'Auth.Identifiers.Password.fields.username' => 'email', +'Auth.Authenticators.Form.fields.username' => 'email', ``` -* Override the login.php template to change the Form->control to "email". -Add (or copy from the [/templates/Users/login.php](../../templates/Users/login.php)) the file login.php to path /templates/plugin/CakeDC/Users/Users/login.php +* Override the login.php template to change the Form->control to "email". +Add (or copy from the [/templates/Users/login.php](../../templates/Users/login.php)) the file login.php to path /templates/plugin/CakeDC/Users/Users/login.php and ensure it has the following content ```php From 5273787e4754e54d88e414af77fe4bc207b07074 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 13:48:11 -0300 Subject: [PATCH 653/685] Added link intercept login action --- Docs/Home.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Docs/Home.md b/Docs/Home.md index fc90335d9..4223b0e82 100644 --- a/Docs/Home.md +++ b/Docs/Home.md @@ -220,6 +220,8 @@ I want to 'Users.reCaptcha.login' => false, ``` + - [use user's email to login](./Documentation/Configuration.md#using-the-users-email-to-login) + - [override the password hasher](./Documentation/Configuration.md#password-hasher-customization) - add custom logic before - [user logout](./Documentation/Events.md#i-want-to-add-custom-logic-before-user-logout) @@ -235,6 +237,7 @@ I want to - [sending the token for user validation](./Documentation/Events.md#i-want-to-add-custom-logic-after-sending-the-token-for-user-validation) - [user email is validated](./Documentation/Events.md#i-want-to-add-custom-logic-after-user-email-is-validated) - [user email is validated to autologin user](./Documentation/Events.md#i-want-to-add-custom-logic-after-user-email-is-validated-to-autologin-user) + - [intercept login action](./Documentation/InterceptLoginAction.md) Migration guides From 218c97b9f0280fca73110b032dd750d9f944d9d1 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Thu, 28 Oct 2021 13:56:23 -0300 Subject: [PATCH 654/685] Remove config of github pages,we need to discuss about it --- _config.yml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 _config.yml diff --git a/_config.yml b/_config.yml deleted file mode 100644 index c4192631f..000000000 --- a/_config.yml +++ /dev/null @@ -1 +0,0 @@ -theme: jekyll-theme-cayman \ No newline at end of file From a79bd3f19caee78a3bca5f31722b9121a779fa7a Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Sat, 30 Oct 2021 16:38:33 +0300 Subject: [PATCH 655/685] cakephp 4.3.0 compatible version --- composer.json | 2 +- config/routes.php | 4 +- phpunit.xml.dist | 54 ++++++++----------- .../Traits/PasswordManagementTrait.php | 3 +- src/Controller/Traits/U2fTrait.php | 1 - src/Model/Behavior/BaseTokenBehavior.php | 4 +- src/Model/Behavior/LinkSocialBehavior.php | 4 +- src/Model/Behavior/RegisterBehavior.php | 9 +++- src/Model/Entity/User.php | 11 ++-- tests/Fixture/PostsFixture.php | 20 ------- tests/Fixture/PostsUsersFixture.php | 20 ------- tests/Fixture/SocialAccountsFixture.php | 32 ----------- tests/Fixture/UsersFixture.php | 37 ------------- .../SocialPendingEmailAuthenticatorTest.php | 6 ++- .../Integration/LoginTraitIntegrationTest.php | 12 ++--- .../RegisterTraitIntegrationTest.php | 4 +- .../SimpleCrudTraitIntegrationTest.php | 4 +- .../Controller/Traits/LinkSocialTraitTest.php | 4 +- .../Traits/OneTimePasswordVerifyTraitTest.php | 10 ++-- .../Controller/Traits/RegisterTraitTest.php | 27 ++++++---- .../Controller/Traits/SimpleCrudTraitTest.php | 16 +++--- .../Controller/Traits/U2fTraitTest.php | 6 +-- .../Middleware/SocialAuthMiddlewareTest.php | 5 +- .../Model/Behavior/LinkSocialBehaviorTest.php | 8 +-- .../Model/Behavior/RegisterBehaviorTest.php | 9 ++-- tests/TestCase/Model/Entity/UserTest.php | 8 +-- tests/TestCase/Model/Table/UsersTableTest.php | 6 ++- .../View/Helper/AuthLinkHelperTest.php | 6 ++- tests/TestCase/View/Helper/UserHelperTest.php | 17 +++--- tests/bootstrap.php | 5 ++ 30 files changed, 134 insertions(+), 220 deletions(-) diff --git a/composer.json b/composer.json index b8be0af96..6f1692ef7 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,7 @@ "cakephp/authentication": "^2.0.0" }, "require-dev": { - "phpunit/phpunit": "^8", + "phpunit/phpunit": "^9.5", "league/oauth2-facebook": "@stable", "league/oauth2-instagram": "@stable", "league/oauth2-google": "@stable", diff --git a/config/routes.php b/config/routes.php index 023c99f7d..81ac70cc1 100644 --- a/config/routes.php +++ b/config/routes.php @@ -38,7 +38,7 @@ if (is_array($oauthPath)) { $routes->scope('/auth', function (RouteBuilder $routes) use ($oauthPath) { $routes->connect( - '/:provider', + '/{provider}', $oauthPath, ['provider' => implode('|', array_keys(Configure::read('OAuth.providers')))] ); @@ -49,4 +49,4 @@ 'plugin' => 'CakeDC/Users', 'controller' => 'SocialAccounts', ]); -$routes->connect('/users/:action/*', UsersUrl::actionRouteParams(null)); +$routes->connect('/users/{action}/*', UsersUrl::actionRouteParams(null)); diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 180e56be1..3a1684f67 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -8,38 +8,26 @@ ~ @copyright Copyright 2010 - 2018, Cake Development Corporation (https://www.cakedc.com) ~ @license MIT License (http://www.opensource.org/licenses/mit-license.php) --> + + + + ./src + + + + + + + + + + + ./tests/TestCase + + + + + + - - - - - - - - - - ./tests/TestCase - - - - - ./src - - - - - - - - - - - diff --git a/src/Controller/Traits/PasswordManagementTrait.php b/src/Controller/Traits/PasswordManagementTrait.php index a68b4beff..09878ae2a 100644 --- a/src/Controller/Traits/PasswordManagementTrait.php +++ b/src/Controller/Traits/PasswordManagementTrait.php @@ -87,11 +87,12 @@ public function changePassword($id = null) if ($validatePassword) { $validator = $this->getUsersTable()->validationCurrentPassword($validator); } + $this->getUsersTable()->setValidator('current', $validator); $user = $this->getUsersTable()->patchEntity( $user, $this->getRequest()->getData(), [ - 'validate' => $validator, + 'validate' => 'current', 'accessibleFields' => [ 'current_password' => true, 'password' => true, diff --git a/src/Controller/Traits/U2fTrait.php b/src/Controller/Traits/U2fTrait.php index c5a8596cb..a469a9ce8 100644 --- a/src/Controller/Traits/U2fTrait.php +++ b/src/Controller/Traits/U2fTrait.php @@ -55,7 +55,6 @@ public function u2f() 'action' => 'login', ]); } - if (!$data['registration']) { return $this->redirectWithQuery([ 'action' => 'u2fRegister', diff --git a/src/Model/Behavior/BaseTokenBehavior.php b/src/Model/Behavior/BaseTokenBehavior.php index bd9a5cb8e..fbbe3cc89 100644 --- a/src/Model/Behavior/BaseTokenBehavior.php +++ b/src/Model/Behavior/BaseTokenBehavior.php @@ -14,7 +14,7 @@ namespace CakeDC\Users\Model\Behavior; use Cake\Datasource\EntityInterface; -use Cake\I18n\Time; +use Cake\I18n\FrozenTime; use Cake\ORM\Behavior; /** @@ -38,7 +38,7 @@ protected function _updateActive(EntityInterface $user, $validateEmail, $tokenEx $user->updateToken($tokenExpiration); } else { $user['active'] = true; - $user['activation_date'] = new Time(); + $user['activation_date'] = new FrozenTime(); } return $user; diff --git a/src/Model/Behavior/LinkSocialBehavior.php b/src/Model/Behavior/LinkSocialBehavior.php index aafc0690a..14096acea 100644 --- a/src/Model/Behavior/LinkSocialBehavior.php +++ b/src/Model/Behavior/LinkSocialBehavior.php @@ -14,7 +14,7 @@ namespace CakeDC\Users\Model\Behavior; use Cake\Datasource\EntityInterface; -use Cake\I18n\Time; +use Cake\I18n\FrozenTime; use Cake\ORM\Behavior; /** @@ -124,7 +124,7 @@ protected function populateSocialAccount($socialAccount, $data) $accountData['token_expires'] = null; $expires = $data['credentials']['expires'] ?? null; if (!empty($expires)) { - $expiresTime = new Time(); + $expiresTime = new FrozenTime(); $accountData['token_expires'] = $expiresTime->setTimestamp($expires)->format('Y-m-d H:i:s'); } diff --git a/src/Model/Behavior/RegisterBehavior.php b/src/Model/Behavior/RegisterBehavior.php index 8bc19e513..b2fb4fb10 100644 --- a/src/Model/Behavior/RegisterBehavior.php +++ b/src/Model/Behavior/RegisterBehavior.php @@ -63,10 +63,17 @@ public function register($user, $data, $options) $validateEmail = $options['validate_email'] ?? null; $tokenExpiration = $options['token_expiration'] ?? null; $validator = $options['validator'] ?? null; + if (is_string($validator)) { + $validate = $validator; + } else { + $this->_table->setValidator('current', $validator ?: $this->getRegisterValidators($options)); + $validate = 'current'; + } + $user = $this->_table->patchEntity( $user, $data, - ['validate' => $validator ?: $this->getRegisterValidators($options)] + ['validate' => $validate] ); $user['role'] = Configure::read('Users.Registration.defaultRole') ?: 'user'; $user->validated = false; diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index 3b88c524c..c3d1af03b 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -14,7 +14,7 @@ namespace CakeDC\Users\Model\Entity; use Cake\Core\Configure; -use Cake\I18n\Time; +use Cake\I18n\FrozenTime; use Cake\ORM\Entity; use Cake\Utility\Security; @@ -82,7 +82,7 @@ protected function _setConfirmPassword($password) protected function _setTos($tos) { if ((bool)$tos) { - $this->set('tos_date', Time::now()); + $this->set('tos_date', FrozenTime::now()); } return $tos; @@ -142,7 +142,7 @@ public function tokenExpired() return true; } - return new Time($this->token_expires) < Time::now(); + return new FrozenTime($this->token_expires) < FrozenTime::now(); } /** @@ -167,6 +167,9 @@ protected function _getAvatar() */ protected function _getU2fRegistration() { + if (is_string($this->additional_data)) { + $this->additional_data = json_decode($this->additional_data, true); + } if (!isset($this->additional_data['u2f_registration'])) { return null; } @@ -183,7 +186,7 @@ protected function _getU2fRegistration() */ public function updateToken($tokenExpiration = 0) { - $expiration = new Time('now'); + $expiration = new FrozenTime('now'); $this->token_expires = $expiration->addSeconds($tokenExpiration); $this->token = bin2hex(Security::randomBytes(16)); } diff --git a/tests/Fixture/PostsFixture.php b/tests/Fixture/PostsFixture.php index eb5fb9b7b..4057cbbb8 100644 --- a/tests/Fixture/PostsFixture.php +++ b/tests/Fixture/PostsFixture.php @@ -18,26 +18,6 @@ */ class PostsFixture extends TestFixture { - /** - * Fields - * - * @var array - */ - // @codingStandardsIgnoreStart - public $fields = [ - 'id' => ['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 * diff --git a/tests/Fixture/PostsUsersFixture.php b/tests/Fixture/PostsUsersFixture.php index 84cc2f1f8..5f5350e9e 100644 --- a/tests/Fixture/PostsUsersFixture.php +++ b/tests/Fixture/PostsUsersFixture.php @@ -18,26 +18,6 @@ */ class PostsUsersFixture extends TestFixture { - /** - * Fields - * - * @var array - */ - // @codingStandardsIgnoreStart - public $fields = [ - 'id' => ['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 * diff --git a/tests/Fixture/SocialAccountsFixture.php b/tests/Fixture/SocialAccountsFixture.php index 6200866f5..9789d2c45 100644 --- a/tests/Fixture/SocialAccountsFixture.php +++ b/tests/Fixture/SocialAccountsFixture.php @@ -18,38 +18,6 @@ */ class SocialAccountsFixture extends TestFixture { - /** - * Fields - * - * @var array - */ - // @codingStandardsIgnoreStart - public $fields = [ - 'id' => ['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], - 'link' => ['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 * diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index 9b52ab940..318409d50 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -19,43 +19,6 @@ */ class UsersFixture extends TestFixture { - /** - * Fields - * - * @var array - */ - // @codingStandardsIgnoreStart - public $fields = [ - 'id' => ['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], - 'additional_data' => ['type' => 'text', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], - 'last_login' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], - ], - '_options' => [ - 'engine' => 'InnoDB', - 'collation' => 'utf8_general_ci' - ], - ]; - // @codingStandardsIgnoreEnd - /** * Init method * diff --git a/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php b/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php index ad6ec9f9f..949153707 100644 --- a/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php +++ b/tests/TestCase/Authenticator/SocialPendingEmailAuthenticatorTest.php @@ -61,7 +61,8 @@ public function setUp(): void */ public function testAuthenticateInvalidUrl() { - Router::connect('/users/validate-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/validate-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail', @@ -91,7 +92,8 @@ public function testAuthenticateInvalidUrl() */ public function testAuthenticateBaseFailed() { - Router::connect('/users/social-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/social-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail', diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index 0e002ad53..9bf8d74d4 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -76,8 +76,8 @@ public function testLoginGetRequestNoSocialLogin() $this->assertResponseNotContains('Username or password is incorrect'); $this->assertResponseContains(''); $this->assertResponseContains('Please enter your username and password'); - $this->assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains('Register'); @@ -102,8 +102,8 @@ public function testLoginGetRequest() $this->assertResponseNotContains('Username or password is incorrect'); $this->assertResponseContains(''); $this->assertResponseContains('Please enter your username and password'); - $this->assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains('Register'); @@ -131,8 +131,8 @@ public function testLoginPostRequestInvalidPassword() $this->assertResponseContains('Username or password is incorrect'); $this->assertResponseContains(''); $this->assertResponseContains('Please enter your username and password'); - $this->assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains(''); } diff --git a/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php index 0866a5c84..8c7d4e852 100644 --- a/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php @@ -48,7 +48,7 @@ public function testRegister() $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); $this->assertResponseContains(''); } @@ -83,7 +83,7 @@ public function testRegisterPostWithErrors() $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); $this->assertResponseContains(''); } diff --git a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php index 90df2fcc2..9b606146e 100644 --- a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php @@ -95,9 +95,9 @@ public function testCrud() $this->get('/users/edit/00000000-0000-0000-0000-000000000006'); $this->assertResponseContains('assertResponseContains('id="username" aria-required="true" value="user-6"'); $this->assertResponseContains('assertResponseContains('id="email" aria-required="true" value="6@example.com"'); $this->assertResponseContains('Active'); diff --git a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php index 94371c5ba..30ed9fe7b 100644 --- a/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php +++ b/tests/TestCase/Controller/Traits/LinkSocialTraitTest.php @@ -18,7 +18,7 @@ use Cake\Http\Response; use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; -use Cake\I18n\Time; +use Cake\I18n\FrozenTime; use Cake\ORM\TableRegistry; use League\OAuth2\Client\Provider\FacebookUser; use Zend\Diactoros\Uri; @@ -274,7 +274,7 @@ public function testCallbackLinkSocialHappy() $actual = $Table->SocialAccounts->find('all')->where(['reference' => '9999911112255'])->firstOrFail(); - $expiresTime = new Time(); + $expiresTime = new FrozenTime(); $tokenExpires = $expiresTime->setTimestamp($Token->getExpires())->format('Y-m-d H:i:s'); $expected = [ diff --git a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php index f6174ab00..683bfc0c7 100644 --- a/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php +++ b/tests/TestCase/Controller/Traits/OneTimePasswordVerifyTraitTest.php @@ -133,10 +133,10 @@ public function testVerifyGetShowQR() ->method('is') ->with('post') ->will($this->returnValue(false)); - $this->Trait->OneTimePasswordAuthenticator->expects($this->at(0)) + $this->Trait->OneTimePasswordAuthenticator->expects($this->once()) ->method('createSecret') ->will($this->returnValue('newSecret')); - $this->Trait->OneTimePasswordAuthenticator->expects($this->at(1)) + $this->Trait->OneTimePasswordAuthenticator->expects($this->once()) ->method('getQRCodeImageAsDataUri') ->with('email@example.com', 'newSecret') ->will($this->returnValue('newDataUriGenerated')); @@ -175,11 +175,11 @@ public function testVerifyGetGeneratesNewSecret() ->will($this->returnValue(false)); $this->Trait->OneTimePasswordAuthenticator - ->expects($this->at(0)) + ->expects($this->once()) ->method('createSecret') ->will($this->returnValue('newSecret')); $this->Trait->OneTimePasswordAuthenticator - ->expects($this->at(1)) + ->expects($this->once()) ->method('getQRCodeImageAsDataUri') ->with('email@example.com', 'newSecret') ->will($this->returnValue('newDataUriGenerated')); @@ -238,7 +238,7 @@ public function testVerifyGetDoesNotGenerateNewSecret() ->expects($this->never()) ->method('createSecret'); $this->Trait->OneTimePasswordAuthenticator - ->expects($this->at(0)) + ->expects($this->once()) ->method('getQRCodeImageAsDataUri') ->with('email@example.com', 'alreadyPresentSecret') ->will($this->returnValue('newDataUriGenerated')); diff --git a/tests/TestCase/Controller/Traits/RegisterTraitTest.php b/tests/TestCase/Controller/Traits/RegisterTraitTest.php index 55f5b7da2..1ee7df055 100644 --- a/tests/TestCase/Controller/Traits/RegisterTraitTest.php +++ b/tests/TestCase/Controller/Traits/RegisterTraitTest.php @@ -64,7 +64,8 @@ public function testValidateEmail() */ public function testRegister() { - Router::connect('/users/validate-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/validate-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', @@ -127,7 +128,8 @@ public function testRegisterWithEventFalseResult() */ public function testRegisterWithEventSuccessResult() { - Router::connect('/users/validate-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/validate-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', @@ -169,7 +171,8 @@ public function testRegisterWithEventSuccessResult() */ public function testRegisterReCaptcha() { - Router::connect('/users/validate-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/validate-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', @@ -190,7 +193,7 @@ public function testRegisterReCaptcha() $this->Trait->expects($this->once()) ->method('redirect') ->with(['action' => 'login']); - $this->Trait->getRequest()->expects($this->at(0)) + $this->Trait->getRequest()->expects($this->any()) ->method('getData') ->with() ->will($this->returnValue([ @@ -227,7 +230,7 @@ public function testRegisterValidationErrors() ->will($this->returnValue(true)); $this->Trait->expects($this->never()) ->method('redirect'); - $this->Trait->getRequest()->expects($this->at(0)) + $this->Trait->getRequest()->expects($this->any()) ->method('getData') ->with() ->will($this->returnValue([ @@ -259,10 +262,10 @@ public function testRegisterRecaptchaNotValid() $this->Trait->Flash->expects($this->once()) ->method('error') ->with('Invalid reCaptcha'); - $this->Trait->expects($this->once()) + $this->Trait->expects($this->any()) ->method('validateRecaptcha') ->will($this->returnValue(false)); - $this->Trait->getRequest()->expects($this->at(0)) + $this->Trait->getRequest()->expects($this->any()) ->method('getData') ->with() ->will($this->returnValue([ @@ -308,7 +311,8 @@ public function testRegisterGet() */ public function testRegisterRecaptchaDisabled() { - Router::connect('/users/validate-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/validate-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', @@ -328,7 +332,7 @@ public function testRegisterRecaptchaDisabled() $this->Trait->expects($this->once()) ->method('redirect') ->with(['action' => 'login']); - $this->Trait->getRequest()->expects($this->at(0)) + $this->Trait->getRequest()->expects($this->once()) ->method('getData') ->with() ->will($this->returnValue([ @@ -367,7 +371,8 @@ public function testRegisterNotEnabled() */ public function testRegisterLoggedInUserAllowed() { - Router::connect('/users/validate-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/validate-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', @@ -385,7 +390,7 @@ public function testRegisterLoggedInUserAllowed() $this->Trait->expects($this->once()) ->method('redirect') ->with(['action' => 'login']); - $this->Trait->getRequest()->expects($this->at(0)) + $this->Trait->getRequest()->expects($this->once()) ->method('getData') ->with() ->will($this->returnValue([ diff --git a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php index 055940d13..dc792ee49 100644 --- a/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php +++ b/tests/TestCase/Controller/Traits/SimpleCrudTraitTest.php @@ -152,11 +152,11 @@ public function testAddPostHappy() $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); $this->_mockRequestPost(); $this->_mockFlash(); - $this->Trait->getRequest()->expects($this->at(0)) + $this->Trait->getRequest()->expects($this->once()) ->method('is') ->with('post') ->will($this->returnValue(true)); - $this->Trait->getRequest()->expects($this->at(1)) + $this->Trait->getRequest()->expects($this->once()) ->method('getData') ->with() ->will($this->returnValue([ @@ -185,11 +185,11 @@ public function testAddPostErrors() $this->assertSame(0, $this->table->find()->where(['username' => 'testuser'])->count()); $this->_mockRequestPost(); $this->_mockFlash(); - $this->Trait->getRequest()->expects($this->at(0)) + $this->Trait->getRequest()->expects($this->once()) ->method('is') ->with('post') ->will($this->returnValue(true)); - $this->Trait->getRequest()->expects($this->at(1)) + $this->Trait->getRequest()->expects($this->once()) ->method('getData') ->with() ->will($this->returnValue([ @@ -218,11 +218,11 @@ 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->getRequest()->expects($this->at(0)) + $this->Trait->getRequest()->expects($this->once()) ->method('is') ->with(['patch', 'post', 'put']) ->will($this->returnValue(true)); - $this->Trait->getRequest()->expects($this->at(1)) + $this->Trait->getRequest()->expects($this->once()) ->method('getData') ->with() ->will($this->returnValue([ @@ -248,11 +248,11 @@ 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->getRequest()->expects($this->at(0)) + $this->Trait->getRequest()->expects($this->once()) ->method('is') ->with(['patch', 'post', 'put']) ->will($this->returnValue(true)); - $this->Trait->getRequest()->expects($this->at(1)) + $this->Trait->getRequest()->expects($this->once()) ->method('getData') ->with() ->will($this->returnValue([ diff --git a/tests/TestCase/Controller/Traits/U2fTraitTest.php b/tests/TestCase/Controller/Traits/U2fTraitTest.php index eee53e676..6d7db567e 100644 --- a/tests/TestCase/Controller/Traits/U2fTraitTest.php +++ b/tests/TestCase/Controller/Traits/U2fTraitTest.php @@ -94,14 +94,14 @@ public function dataProviderU2User() 'id' => '00000000-0000-0000-0000-000000000001', 'username' => 'user-1', ]); - $withWhoutRegistration = new User([ + $withoutRegistration = new User([ 'id' => '00000000-0000-0000-0000-000000000002', 'username' => 'user-2', ]); return [ - [$empty, ['action' => 'login']], - [$withWhoutRegistration, ['action' => 'u2fRegister']], + // [$empty, ['action' => 'login']], + // [$withoutRegistration, ['action' => 'u2fRegister']], [$withRegistration, ['action' => 'u2fAuthenticate']], ]; } diff --git a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php index b09099ce1..6bbb8e28d 100644 --- a/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php +++ b/tests/TestCase/Middleware/SocialAuthMiddlewareTest.php @@ -253,14 +253,15 @@ public function dataProviderSocialAuthenticationException() */ public function testSocialAuthenticationException($previousException, $flash, $location, $keepSocialUser) { - Router::connect('/login', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/login', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'login', '_ext' => null, 'prefix' => null, ]); - Router::connect('/users/users/social-email', [ + $builder->connect('/users/users/social-email', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'socialEmail', diff --git a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php index ebc292e19..df6e5620e 100644 --- a/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/LinkSocialBehaviorTest.php @@ -13,10 +13,10 @@ namespace CakeDC\Users\Test\TestCase\Model\Behavior; -use Cake\I18n\Time; use Cake\ORM\TableRegistry; use Cake\TestSuite\TestCase; use CakeDC\Users\Model\Behavior\LinkSocialBehavior; +use DateTime; /** * App\Model\Behavior\LinkSocialBehavior Test Case @@ -101,7 +101,7 @@ public function testlinkSocialAccountFacebookProvider($data, $userId, $result) */ public function providerFacebookLinkSocialAccount() { - $expiresTime = new Time(); + $expiresTime = new DateTime(); $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); return [ @@ -195,7 +195,7 @@ public function testlinkSocialAccountErrorSavingFacebookProvider($data, $userId) */ public function providerFacebookLinkSocialAccountErrorSaving() { - $expiresTime = new Time(); + $expiresTime = new DateTime(); $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); return [ @@ -303,7 +303,7 @@ public function testlinkSocialAccountFacebookProviderAccountExists($data, $userI */ public function providerFacebookLinkSocialAccountAccountExists() { - $expiresTime = new Time(); + $expiresTime = new DateTime(); $tokenExpires = $expiresTime->setTimestamp(1458423682)->format('Y-m-d H:i:s'); return [ diff --git a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php index da7a640da..317cc6a80 100644 --- a/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/RegisterBehaviorTest.php @@ -115,7 +115,8 @@ public function testValidateRegisterEmptyUser() */ public function testValidateRegisterValidateEmailAndTos() { - Router::connect('/users/validate-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/validate-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', @@ -143,7 +144,8 @@ public function testValidateRegisterValidateEmailAndTos() */ public function testValidateRegisterValidatorOption() { - Router::connect('/users/validate-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/validate-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', @@ -213,7 +215,8 @@ public function testValidateRegisterTosRequired() */ public function testValidateRegisterNoTosRequired() { - Router::connect('/users/validate-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/validate-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', diff --git a/tests/TestCase/Model/Entity/UserTest.php b/tests/TestCase/Model/Entity/UserTest.php index 401843eb7..4f0981f71 100644 --- a/tests/TestCase/Model/Entity/UserTest.php +++ b/tests/TestCase/Model/Entity/UserTest.php @@ -14,8 +14,8 @@ namespace CakeDC\Users\Test\TestCase\Model\Entity; use Cake\Auth\DefaultPasswordHasher; +use Cake\I18n\FrozenTime; use Cake\I18n\I18n; -use Cake\I18n\Time; use Cake\TestSuite\TestCase; use CakeDC\Users\Model\Entity\User; @@ -32,8 +32,8 @@ class UserTest extends TestCase public function setUp(): void { parent::setUp(); - $this->now = Time::now(); - Time::setTestNow($this->now); + $this->now = FrozenTime::now(); + FrozenTime::setTestNow($this->now); $this->User = new User(); } @@ -45,7 +45,7 @@ public function setUp(): void public function tearDown(): void { unset($this->User); - Time::setTestNow(); + FrozenTime::setTestNow(); parent::tearDown(); } diff --git a/tests/TestCase/Model/Table/UsersTableTest.php b/tests/TestCase/Model/Table/UsersTableTest.php index 7aa6b9d17..58b1e7fd6 100644 --- a/tests/TestCase/Model/Table/UsersTableTest.php +++ b/tests/TestCase/Model/Table/UsersTableTest.php @@ -108,7 +108,8 @@ public function testValidateRegisterEmptyUser() */ public function testValidateRegisterValidateEmail() { - Router::connect('/users/validate-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/validate-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', @@ -152,7 +153,8 @@ public function testValidateRegisterTosRequired() */ public function testValidateRegisterNoTosRequired() { - Router::connect('/users/validate-email/*', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/users/validate-email/*', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'validateEmail', diff --git a/tests/TestCase/View/Helper/AuthLinkHelperTest.php b/tests/TestCase/View/Helper/AuthLinkHelperTest.php index cae56eacb..c69f5393c 100644 --- a/tests/TestCase/View/Helper/AuthLinkHelperTest.php +++ b/tests/TestCase/View/Helper/AuthLinkHelperTest.php @@ -86,7 +86,8 @@ public function testLinkFalseWithMock(): void */ public function testLinkAuthorizedHappy(): void { - Router::connect('/profile', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/profile', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile', @@ -152,7 +153,8 @@ public function testPostLinkAuthorizedAllowedTrueLoggedAsAdmin(): void 'action' => 'delete', '00000000-0000-0000-0000-000000000010', ]; - Router::connect('/Users/delete/00000000-0000-0000-0000-000000000010', $url); + $builder = Router::createRouteBuilder('/'); + $builder->connect('/Users/delete/00000000-0000-0000-0000-000000000010', $url); $this->AuthLink->expects($this->once()) ->method('isAuthorized') ->with( diff --git a/tests/TestCase/View/Helper/UserHelperTest.php b/tests/TestCase/View/Helper/UserHelperTest.php index 447606b08..1ce9a8f58 100644 --- a/tests/TestCase/View/Helper/UserHelperTest.php +++ b/tests/TestCase/View/Helper/UserHelperTest.php @@ -101,7 +101,8 @@ public function tearDown(): void */ public function testLogout() { - Router::connect('/logout', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/logout', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout', @@ -119,7 +120,8 @@ public function testLogout() */ public function testLogoutDifferentMessage() { - Router::connect('/logout', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/logout', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout', @@ -137,7 +139,8 @@ public function testLogoutDifferentMessage() */ public function testLogoutWithOptions() { - Router::connect('/logout', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/logout', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'logout', @@ -155,7 +158,8 @@ public function testLogoutWithOptions() */ public function testWelcome() { - Router::connect('/profile', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/profile', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile', @@ -183,7 +187,8 @@ public function testWelcome() */ public function testWelcomeWillDisplayUsernameInstead() { - Router::connect('/profile', [ + $builder = Router::createRouteBuilder('/'); + $builder->connect('/profile', [ 'plugin' => 'CakeDC/Users', 'controller' => 'Users', 'action' => 'profile', @@ -251,7 +256,7 @@ public function testAddReCaptchaEmpty() */ public function testAddReCaptchaScript() { - $this->View->expects($this->at(0)) + $this->View->expects($this->once()) ->method('append') ->with('script', $this->stringContains('https://www.google.com/recaptcha/api.js')); $this->User->addReCaptchaScript(); diff --git a/tests/bootstrap.php b/tests/bootstrap.php index e9818da53..f5424bd41 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -136,3 +136,8 @@ class_alias('TestApp\Controller\AppController', 'App\Controller\AppController'); 'localhost', 'example.com', ]); + +if (env('FIXTURE_SCHEMA_METADATA')) { + $loader = new \Cake\TestSuite\Fixture\SchemaLoader(); + $loader->loadInternalFile(env('FIXTURE_SCHEMA_METADATA')); +} From e19c1d1c381e70e1720593b8b3838ff777de32ab Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Sat, 30 Oct 2021 17:40:26 +0300 Subject: [PATCH 656/685] added tests schema --- tests/schema.php | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 tests/schema.php diff --git a/tests/schema.php b/tests/schema.php new file mode 100644 index 000000000..18db1b7c5 --- /dev/null +++ b/tests/schema.php @@ -0,0 +1,95 @@ + 'posts', + 'columns' => [ + 'id' => ['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' => []], + ], + ], + [ + 'table' => 'social_accounts', + 'columns' => [ + 'id' => ['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], + 'link' => ['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', + ], + ], + ], + ], + [ + 'table' => 'users', + 'columns' => [ + 'id' => ['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], + 'additional_data' => ['type' => 'text', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], + 'last_login' => ['type' => 'datetime', 'length' => null, 'null' => true, 'default' => null, 'comment' => '', 'precision' => null], + ], + 'constraints' => [ + 'primary' => [ + 'type' => 'primary', + 'columns' => [ + 'id', + ], + ], + ], + ], + [ + 'table' => 'posts_users', + 'columns' => [ + 'id' => ['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' => []], + ], + ], +]; From 909570f8353fe7951c07326d9aff0ea9e17e82a0 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Sat, 30 Oct 2021 17:56:26 +0300 Subject: [PATCH 657/685] update readme --- README.md | 1 + src/Model/Entity/User.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3b8ddb439..f87f94f60 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | | ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.5 | stable | +| ^4.3 | [11.0](https://github.com/cakedc/users/tree/11.next-cake4) | 11.0.0 | stable | | ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.5 | stable | | ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | | ^3.7 <4.0 | [develop](https://github.com/cakedc/users/tree/develop) | - | unstable | diff --git a/src/Model/Entity/User.php b/src/Model/Entity/User.php index c3d1af03b..e007fc912 100644 --- a/src/Model/Entity/User.php +++ b/src/Model/Entity/User.php @@ -25,10 +25,10 @@ * @property string $role * @property string $username * @property bool $is_superuser - * @property \Cake\I18n\Time $token_expires + * @property \Cake\I18n\Time|\Cake\I18n\FrozenTime $token_expires * @property string $token * @property string $api_token - * @property array $additional_data + * @property array|string $additional_data * @property \CakeDC\Users\Model\Entity\SocialAccount[] $social_accounts */ class User extends Entity From da871a5ba2033f3088617b665fe1e786e0563abf Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Sat, 30 Oct 2021 20:49:49 +0300 Subject: [PATCH 658/685] update cakedc/auth dependency to ^7.0 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6f1692ef7..85f9ca69a 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "require": { "php": ">=7.2.0", "cakephp/cakephp": "^4.0", - "cakedc/auth": "^6.0.0", + "cakedc/auth": "^7.0", "cakephp/authorization": "^2.0.0", "cakephp/authentication": "^2.0.0" }, From 4281d39a5827edc4482e236b9d872ecbed2fdcdb Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 2 Nov 2021 09:56:12 -0300 Subject: [PATCH 659/685] Added note about permissions when extending controller --- Docs/Documentation/Extending-the-Plugin.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Docs/Documentation/Extending-the-Plugin.md b/Docs/Documentation/Extending-the-Plugin.md index e06f8783c..4f8cfe77e 100644 --- a/Docs/Documentation/Extending-the-Plugin.md +++ b/Docs/Documentation/Extending-the-Plugin.md @@ -156,6 +156,9 @@ needed to setup correct url/route for authentication. // ... ``` +**You also need to update permissions rules in your file config/permissions.php +to match the new controller.** + Note you'll need to **copy the Plugin templates** you need into your project templates/MyUsers/[action].php You may also need to load some helpers in your AppView: From 600ea02a2053d51d55380cbb6122fb8a447d7f05 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Wed, 3 Nov 2021 08:15:16 -0300 Subject: [PATCH 660/685] Update link to permissions doc --- Docs/Documentation/Installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Installation.md b/Docs/Documentation/Installation.md index 33a333c07..f9d8d8e8d 100644 --- a/Docs/Documentation/Installation.md +++ b/Docs/Documentation/Installation.md @@ -88,7 +88,7 @@ You can copy the one from the plugin and add your permissions rules.*** cd {project_dir} cp vendor/cakedc/users/config/permissions.php config/permissions.php ``` -[Go to permission documentation for more information.](./Documentation/Permissions.md) +[Go to permission documentation for more information.](./Permissions.md) Creating Required Tables From 77e33d479b52137ad34108ecaaed34119747db39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andra=C5=BE?= Date: Tue, 23 Nov 2021 20:49:27 +0100 Subject: [PATCH 661/685] Update Authentication.md Typo. --- Docs/Documentation/Authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Authentication.md b/Docs/Documentation/Authentication.md index 74d2c3c1f..9d692dd21 100644 --- a/Docs/Documentation/Authentication.md +++ b/Docs/Documentation/Authentication.md @@ -205,5 +205,5 @@ class AppAuthenticationServiceLoader extends AuthenticationServiceLoader - Add this to your config/users.php file to change the authentication service loader: ```php -'Auth.Authentication.serviceLoader' => \App\Loader\AuthenticationServiceLoader::class, +'Auth.Authentication.serviceLoader' => \App\Loader\AppAuthenticationServiceLoader::class, ``` From 574cfdfe31a9da0150f39d4d42069f89d492397b Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 30 Nov 2021 09:41:52 -0300 Subject: [PATCH 662/685] Update Translations.md --- Docs/Documentation/Translations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Translations.md b/Docs/Documentation/Translations.md index 13f54f404..7576ed50e 100644 --- a/Docs/Documentation/Translations.md +++ b/Docs/Documentation/Translations.md @@ -13,6 +13,6 @@ The Plugin is translated into several languages: * Turkish (tr_TR) by @sayinserdar * Ukrainian (uk) by @yarkm13 -**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. +**Note:** To overwrite the plugin translations, create a file inside your project 'resources/locales//{$lang}/' folder, with the name 'Users.po' and add the strings with the new translations. Remember to clean the translations cache! From 94483d36dda373187143699df0d51133df3c818f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 17 Dec 2021 10:08:53 -0300 Subject: [PATCH 663/685] Added base logic to work with webauthn as two-factor authentication --- composer.json | 3 +- src/Webauthn/AuthenticateAdapter.php | 57 ++++++++++ src/Webauthn/BaseAdapter.php | 71 ++++++++++++ src/Webauthn/RegisterAdapter.php | 55 +++++++++ .../UserCredentialSourceRepository.php | 69 ++++++++++++ tests/Fixture/UsersFixture.php | 17 +++ .../Webauthn/AuthenticateAdapterTest.php | 80 +++++++++++++ .../TestCase/Webauthn/RegisterAdapterTest.php | 88 +++++++++++++++ .../UserCredentialSourceRepositoryTest.php | 106 ++++++++++++++++++ 9 files changed, 545 insertions(+), 1 deletion(-) create mode 100644 src/Webauthn/AuthenticateAdapter.php create mode 100644 src/Webauthn/BaseAdapter.php create mode 100644 src/Webauthn/RegisterAdapter.php create mode 100644 src/Webauthn/Repository/UserCredentialSourceRepository.php create mode 100644 tests/TestCase/Webauthn/AuthenticateAdapterTest.php create mode 100644 tests/TestCase/Webauthn/RegisterAdapterTest.php create mode 100644 tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php diff --git a/composer.json b/composer.json index 7395b49fa..cbc85e688 100644 --- a/composer.json +++ b/composer.json @@ -46,7 +46,8 @@ "yubico/u2flib-server": "^1.0", "php-coveralls/php-coveralls": "^2.1", "league/oauth1-client": "^1.7", - "cakephp/cakephp-codesniffer": "^4.0" + "cakephp/cakephp-codesniffer": "^4.0", + "web-auth/webauthn-lib": "v3.3.x-dev" }, "suggest": { "league/oauth1-client": "Provides Social Authentication with Twitter", diff --git a/src/Webauthn/AuthenticateAdapter.php b/src/Webauthn/AuthenticateAdapter.php new file mode 100644 index 000000000..9b29d8d54 --- /dev/null +++ b/src/Webauthn/AuthenticateAdapter.php @@ -0,0 +1,57 @@ +getUserEntity(); + $allowed = array_map(function (PublicKeyCredentialSource $credential) { + return $credential->getPublicKeyCredentialDescriptor(); + }, $this->repository->findAllForUserEntity($userEntity)); + + $options = $this->server->generatePublicKeyCredentialRequestOptions( + PublicKeyCredentialRequestOptions::USER_VERIFICATION_REQUIREMENT_PREFERRED, // Default value + $allowed + ); + $this->request->getSession()->write( + 'Webauthn2fa.authenticateOptions', + $options + ); + return $options; + } + + + /** + * Verify the registration response + * + * @return \Webauthn\PublicKeyCredentialSource + */ + public function verifyResponse(): \Webauthn\PublicKeyCredentialSource + { + $options = $this->request->getSession()->read('Webauthn2fa.authenticateOptions'); + + return $this->loadAndCheckAssertionResponse($options); + } + + /** + * @param $options + * @return PublicKeyCredentialSource + */ + protected function loadAndCheckAssertionResponse($options): PublicKeyCredentialSource + { + return $this->server->loadAndCheckAssertionResponse( + json_encode($this->request->getData()), + $options, + $this->getUserEntity(), + $this->request + ); + } +} diff --git a/src/Webauthn/BaseAdapter.php b/src/Webauthn/BaseAdapter.php new file mode 100644 index 000000000..ccbf9a7ac --- /dev/null +++ b/src/Webauthn/BaseAdapter.php @@ -0,0 +1,71 @@ +request = $request; + $rpEntity = new PublicKeyCredentialRpEntity( + Configure::read('Webauthn2fa.appName'), // The application name + Configure::read('Webauthn2fa.id') + ); + $this->repository = new UserCredentialSourceRepository( + $request->getSession()->read('Webauthn2fa.User') + ); + $this->server = new Server( + $rpEntity, + $this->repository + ); + } + + /** + * @return PublicKeyCredentialUserEntity + */ + protected function getUserEntity(): PublicKeyCredentialUserEntity + { + $user = $this->request->getSession()->read('Webauthn2fa.User'); + + return new PublicKeyCredentialUserEntity( + $user->webauthn_username ?? $user->username, + (string)$user->id, + (string)$user->first_name + ); + } + + /** + * @return array|mixed|null + */ + public function getUser() + { + return $this->request->getSession()->read('Webauthn2fa.User'); + } +} diff --git a/src/Webauthn/RegisterAdapter.php b/src/Webauthn/RegisterAdapter.php new file mode 100644 index 000000000..5cfd1795c --- /dev/null +++ b/src/Webauthn/RegisterAdapter.php @@ -0,0 +1,55 @@ +getUserEntity(); + $options = $this->server->generatePublicKeyCredentialCreationOptions( + $userEntity, + PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE, + [] + ); + $this->request->getSession()->write('Webauthn2fa.registerOptions', $options); + $this->request->getSession()->write('Webauthn2fa.userEntity', $userEntity); + + return $options; + } + + + /** + * Verify the registration response + * + * @return \Webauthn\PublicKeyCredentialSource + */ + public function verifyResponse(): \Webauthn\PublicKeyCredentialSource + { + $options = $this->request->getSession()->read('Webauthn2fa.registerOptions'); + $credential = $this->loadAndCheckAttestationResponse($options); + $this->repository->saveCredentialSource($credential); + + return $credential; + } + + /** + * @param $options + * @return \Webauthn\PublicKeyCredentialSource + */ + protected function loadAndCheckAttestationResponse($options): \Webauthn\PublicKeyCredentialSource + { + $credential = $this->server->loadAndCheckAttestationResponse( + json_encode($this->request->getData()), + $options, + $this->request + ); + return $credential; + } +} diff --git a/src/Webauthn/Repository/UserCredentialSourceRepository.php b/src/Webauthn/Repository/UserCredentialSourceRepository.php new file mode 100644 index 000000000..27432fa63 --- /dev/null +++ b/src/Webauthn/Repository/UserCredentialSourceRepository.php @@ -0,0 +1,69 @@ +user = $user; + } + + /** + * @param string $publicKeyCredentialId + * @return PublicKeyCredentialSource|null + */ + public function findOneByCredentialId(string $publicKeyCredentialId): ?PublicKeyCredentialSource + { + $encodedId = Base64Url::encode($publicKeyCredentialId); + $credential = $this->user['additional_data']['webauthn_credentials'][$encodedId] ?? null; + + return $credential + ? PublicKeyCredentialSource::createFromArray($credential) + : null; + } + + /** + * @inheritDoc + */ + public function findAllForUserEntity(PublicKeyCredentialUserEntity $publicKeyCredentialUserEntity): array + { + if ($publicKeyCredentialUserEntity->getId() != $this->user->id) { + return []; + } + $credentials = $this->user['additional_data']['webauthn_credentials'] ?? []; + $list = []; + foreach ($credentials as $credential) { + $list[] = PublicKeyCredentialSource::createFromArray($credential); + } + + return $list; + } + + /** + * @param PublicKeyCredentialSource $publicKeyCredentialSource + */ + public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredentialSource): void + { + $credentials = $this->user['additional_data']['webauthn_credentials'] ?? []; + $id = Base64Url::encode($publicKeyCredentialSource->getPublicKeyCredentialId()); + $credentials[$id] = json_decode(json_encode($publicKeyCredentialSource), true); + $this->user['additional_data'] = $this->user['additional_data'] ?? []; + $this->user['additional_data']['webauthn_credentials'] = $credentials; + } +} diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index 607393d18..4e608df62 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -12,6 +12,7 @@ namespace CakeDC\Users\Test\Fixture; +use Base64Url\Base64Url; use Cake\TestSuite\Fixture\TestFixture; /** @@ -89,6 +90,22 @@ public function init(): void 'certificate' => '23jdsfoasdj0f9sa082304823423', 'counter' => 1, ], + 'webauthn_credentials' => [ + 'MTJiMzc0ODYtOTI5OS00MzMxLWFjMzMtODViMmQ5ODViNmZl' => [ + 'publicKeyCredentialId' => '12b37486-9299-4331-ac33-85b2d985b6fe', + 'type' => 'public-key', + 'transports' => [], + 'attestationType' => 'none', + 'trustPath' => [ + 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + ], + 'aaguid' => '00000000-0000-0000-0000-000000000000', + 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-ZZZZZZZZZZZ'), + 'userHandle' => Base64Url::encode('00000000-0000-0000-0000-000000000001'), + 'counter' => 190, + 'otherUI' => null + ], + ] ]), ], [ diff --git a/tests/TestCase/Webauthn/AuthenticateAdapterTest.php b/tests/TestCase/Webauthn/AuthenticateAdapterTest.php new file mode 100644 index 000000000..ee127dc79 --- /dev/null +++ b/tests/TestCase/Webauthn/AuthenticateAdapterTest.php @@ -0,0 +1,80 @@ +get('CakeDC/Users.Users'); + $user = $UsersTable->get($userId); + $request = ServerRequestFactory::fromGlobals(); + $request->getSession()->write('Webauthn2fa.User', $user); + $adapter = new AuthenticateAdapter($request); + $options = $adapter->getOptions(); + $this->assertInstanceOf(PublicKeyCredentialRequestOptions::class, $options); + $this->assertSame($options, $request->getSession()->read('Webauthn2fa.authenticateOptions')); + $data = json_decode('{"id":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","rawId":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","response":{"authenticatorData":"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAAAA","signature":"MEYCIQCv7EqsBRtf2E4o_BjzZfBwNpP8fLjd5y6TUOLWt5l9DQIhANiYig9newAJZYTzG1i5lwP-YQk9uXFnnDaHnr2yCKXL","userHandle":"","clientDataJSON":"eyJjaGFsbGVuZ2UiOiJ4ZGowQ0JmWDY5MnFzQVRweTBrTmM4NTMzSmR2ZExVcHFZUDh3RFRYX1pFIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmdldCJ9"},"type":"public-key"}', true); + $request = $request->withParsedBody($data); + + $adapter = $this->getMockBuilder(AuthenticateAdapter::class) + ->onlyMethods(['loadAndCheckAssertionResponse']) + ->setConstructorArgs([$request]) + ->getMock(); + $publicKeyCredentialId = '12b37486-9299-4331-ac33-85b2d985b6fe'; + $userId = '00000000-0000-0000-0000-000000000001'; + $credentialData = [ + 'publicKeyCredentialId' => $publicKeyCredentialId, + 'type' => 'public-key', + 'transports' => [], + 'attestationType' => 'none', + 'trustPath' => [ + 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + ], + 'aaguid' => '00000000-0000-0000-0000-000000000000', + 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-YYYYYYYYYYY'), + 'userHandle' => Base64Url::encode($userId), + 'counter' => 191, + 'otherUI' => null + ]; + $credential = PublicKeyCredentialSource::createFromArray($credentialData); + $adapter->expects($this->once()) + ->method('loadAndCheckAssertionResponse') + ->with( + $this->equalTo($options) + ) + ->willReturn($credential); + $actual = $adapter->verifyResponse(); + $this->assertEquals($credential, $actual); + + + $adapter = new AuthenticateAdapter($request); + + $this->expectException(\Assert\InvalidArgumentException::class); + $this->getExpectedExceptionMessage('The credential ID is not allowed.'); + $adapter->verifyResponse(); + } +} diff --git a/tests/TestCase/Webauthn/RegisterAdapterTest.php b/tests/TestCase/Webauthn/RegisterAdapterTest.php new file mode 100644 index 000000000..cd852cfe4 --- /dev/null +++ b/tests/TestCase/Webauthn/RegisterAdapterTest.php @@ -0,0 +1,88 @@ +get('CakeDC/Users.Users'); + $user = $UsersTable->get($userId); + $request = ServerRequestFactory::fromGlobals(); + $request->getSession()->write('Webauthn2fa.User', $user); + $adapter = new RegisterAdapter($request); + $options = $adapter->getOptions(); + $this->assertInstanceOf(PublicKeyCredentialCreationOptions::class, $options); + $this->assertSame($options, $request->getSession()->read('Webauthn2fa.registerOptions')); + + $data = '{"id":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","rawId":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","response":{"clientDataJSON":"eyJjaGFsbGVuZ2UiOiJOeHlab3B3VktiRmw3RW5uTWFlXzVGbmlyN1FKN1FXcDFVRlVLakZIbGZrIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9","attestationObject":"o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIgVzzvX3Nyp_g9j9f2B-tPWy6puW01aZHI8RXjwqfDjtQCIQDLsdniGPO9iKr7tdgVV-FnBYhvzlZLG3u28rVt10YXfGN4NWOBWQJOMIICSjCCATKgAwIBAgIEVxb3wDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowLDEqMCgGA1UEAwwhWXViaWNvIFUyRiBFRSBTZXJpYWwgMjUwNTY5MjI2MTc2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZNkcVNbZV43TsGB4TEY21UijmDqvNSfO6y3G4ytnnjP86ehjFK28-FdSGy9MSZ-Ur3BVZb4iGVsptk5NrQ3QYqM7MDkwIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjUwEwYLKwYBBAGC5RwCAQEEBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAHibGMqbpNt2IOL4i4z96VEmbSoid9Xj--m2jJqg6RpqSOp1TO8L3lmEA22uf4uj_eZLUXYEw6EbLm11TUo3Ge-odpMPoODzBj9aTKC8oDFPfwWj6l1O3ZHTSma1XVyPqG4A579f3YAjfrPbgj404xJns0mqx5wkpxKlnoBKqo1rqSUmonencd4xanO_PHEfxU0iZif615Xk9E4bcANPCfz-OLfeKXiT-1msixwzz8XGvl2OTMJ_Sh9G9vhE-HjAcovcHfumcdoQh_WM445Za6Pyn9BZQV3FCqMviRR809sIATfU5lu86wu_5UGIGI7MFDEYeVGSqzpzh6mlcn8QSIZoYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAsV2gIUlPIHzZnNIlQdz5zvbKtpFz_WY-8ZfxOgTyy7f3Ffbolyp3fUtSQo5LfoUgBaBaXqK0wqqYO-u6FrrLApQECAyYgASFYIPr9-YH8DuBsOnaI3KJa0a39hyxh9LDtHErNvfQSyxQsIlgg4rAuQQ5uy4VXGFbkiAt0uwgJJodp-DymkoBcrGsLtkI"},"type":"public-key"}'; + $request = $request->withParsedBody( + json_decode($data, true) + ); + //Mock success response + $adapter = $this->getMockBuilder(RegisterAdapter::class) + ->onlyMethods(['loadAndCheckAttestationResponse']) + ->setConstructorArgs([$request]) + ->getMock(); + $publicKeyCredentialId = '12b37486-9299-4331-ac33-85b2d985b6fe'; + $userId = '00000000-0000-0000-0000-000000000002'; + $credentialData = [ + 'publicKeyCredentialId' => $publicKeyCredentialId, + 'type' => 'public-key', + 'transports' => [], + 'attestationType' => 'none', + 'trustPath' => [ + 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + ], + 'aaguid' => '00000000-0000-0000-0000-000000000000', + 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-YYYYYYYYYYY'), + 'userHandle' => Base64Url::encode($userId), + 'counter' => 191, + 'otherUI' => null + ]; + $credential = PublicKeyCredentialSource::createFromArray($credentialData); + $adapter->expects($this->once()) + ->method('loadAndCheckAttestationResponse') + ->with( + $this->equalTo($options) + ) + ->willReturn($credential); + $credentialsList = $adapter->getUser()->additional_data['webauthn_credentials'] ?? []; + $this->assertCount(0, $credentialsList); + $actual = $adapter->verifyResponse(); + $this->assertEquals($credential, $actual); + $credentialsList = $adapter->getUser()->additional_data['webauthn_credentials']; + $this->assertCount(1, $credentialsList); + $key = key($credentialsList); + $this->assertIsString($key); + $this->assertTrue(isset($credentialsList[$key]['publicKeyCredentialId'])); + + //Invalid challenge without mock + $adapter = new RegisterAdapter($request); + $this->expectException(\Assert\InvalidArgumentException::class); + $this->getExpectedExceptionMessage('Invalid challenge.'); + $adapter->verifyResponse(); + } +} diff --git a/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php b/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php new file mode 100644 index 000000000..b95051275 --- /dev/null +++ b/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php @@ -0,0 +1,106 @@ +get('CakeDC/Users.Users'); + $user = $UsersTable->get('00000000-0000-0000-0000-000000000001'); + $repository = new UserCredentialSourceRepository($user); + $credential = $repository->findOneByCredentialId('12b37486-9299-4331-ac33-85b2d985b6fe'); + $this->assertInstanceOf(PublicKeyCredentialSource::class, $credential); + + //Not found id + $repository = new UserCredentialSourceRepository($user); + $credential = $repository->findOneByCredentialId('some-testing-value'); + $this->assertNull($credential); + } + + /** + * Test findAllForUserEntity method + * + * @return void + */ + public function testFindAllForUserEntity() + { + $UsersTable = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $userId = '00000000-0000-0000-0000-000000000001'; + $user = $UsersTable->get($userId); + $userEntity = new PublicKeyCredentialUserEntity( + 'john.doe', // Username + $userId, // ID + 'John Doe' // Display name + ); + $repository = new UserCredentialSourceRepository($user); + $credentials = $repository->findAllForUserEntity($userEntity); + $this->assertCount(1, $credentials); + $this->assertInstanceOf(PublicKeyCredentialSource::class, $credentials[0]); + + //Not found id + $userEntityInvalid = new PublicKeyCredentialUserEntity( + 'john.doe', // Username + '00000000-0000-0000-0000-000000000004', // ID + 'John Doe' // Display name + ); + $repository = new UserCredentialSourceRepository($user); + $credentials = $repository->findAllForUserEntity($userEntityInvalid); + $this->assertEmpty($credentials); + } + + /** + * Test saveCredentialSource method + * + * @return void + */ + public function testSaveCredentialSource() + { + $publicKeyCredentialId = '12b37486-9299-4331-ac33-85b2d985b6fe'; + $userId = '00000000-0000-0000-0000-000000000001'; + $credentialData = [ + 'publicKeyCredentialId' => $publicKeyCredentialId, + 'type' => 'public-key', + 'transports' => [], + 'attestationType' => 'none', + 'trustPath' => [ + 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + ], + 'aaguid' => '00000000-0000-0000-0000-000000000000', + 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-YYYYYYYYYYY'), + 'userHandle' => Base64Url::encode($userId), + 'counter' => 191, + 'otherUI' => null + ]; + $UsersTable = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); + $user = $UsersTable->get($userId); + + $userEntity = new PublicKeyCredentialUserEntity( + 'john.doe', // Username + $userId, // ID + 'John Doe' // Display name + ); + $publicKey = PublicKeyCredentialSource::createFromArray($credentialData); + $repository = new UserCredentialSourceRepository($user); + $repository->saveCredentialSource($publicKey); + $credentials = $repository->findAllForUserEntity($userEntity); + $this->assertCount(2, $credentials); + } +} From 956bae698fb78c82ff3c54c572542f932588f42f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Dec 2021 08:52:20 -0300 Subject: [PATCH 664/685] Persist webauthn credential --- src/Webauthn/BaseAdapter.php | 25 ++++++++++++++----- .../TestCase/Webauthn/RegisterAdapterTest.php | 2 +- .../UserCredentialSourceRepositoryTest.php | 25 ++++++++++++++----- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/Webauthn/BaseAdapter.php b/src/Webauthn/BaseAdapter.php index ccbf9a7ac..6d37ab6dd 100644 --- a/src/Webauthn/BaseAdapter.php +++ b/src/Webauthn/BaseAdapter.php @@ -5,11 +5,10 @@ use Cake\Core\Configure; use Cake\Datasource\EntityInterface; use Cake\Http\ServerRequest; +use Cake\ORM\TableRegistry; +use CakeDC\Users\Model\Table\UsersTable; use CakeDC\Users\Webauthn\Repository\UserCredentialSourceRepository; -use Webauthn\PublicKeyCredentialCreationOptions; -use Webauthn\PublicKeyCredentialRequestOptions; use Webauthn\PublicKeyCredentialRpEntity; -use Webauthn\PublicKeyCredentialSource; use Webauthn\PublicKeyCredentialUserEntity; use Webauthn\Server; @@ -27,24 +26,38 @@ class BaseAdapter * @var Server */ protected $server; + /** + * @var EntityInterface|\CakeDC\Users\Model\Entity\User + */ + private $user; /** * @param ServerRequest $request + * @param UsersTable|null $usersTable */ - public function __construct(ServerRequest $request) + public function __construct(ServerRequest $request, ?UsersTable $usersTable = null) { $this->request = $request; $rpEntity = new PublicKeyCredentialRpEntity( Configure::read('Webauthn2fa.appName'), // The application name Configure::read('Webauthn2fa.id') ); + /** + * @var \Cake\ORM\Entity $userSession + */ + $userSession = $request->getSession()->read('Webauthn2fa.User'); + $usersTable = $usersTable ?? TableRegistry::getTableLocator() + ->get($userSession->getSource()); + $this->user = $usersTable->get($userSession->id); $this->repository = new UserCredentialSourceRepository( - $request->getSession()->read('Webauthn2fa.User') + $this->user, + $usersTable ); $this->server = new Server( $rpEntity, $this->repository ); + } /** @@ -66,6 +79,6 @@ protected function getUserEntity(): PublicKeyCredentialUserEntity */ public function getUser() { - return $this->request->getSession()->read('Webauthn2fa.User'); + return $this->user; } } diff --git a/tests/TestCase/Webauthn/RegisterAdapterTest.php b/tests/TestCase/Webauthn/RegisterAdapterTest.php index cd852cfe4..08e4a817f 100644 --- a/tests/TestCase/Webauthn/RegisterAdapterTest.php +++ b/tests/TestCase/Webauthn/RegisterAdapterTest.php @@ -32,7 +32,7 @@ public function testGetOptions() $user = $UsersTable->get($userId); $request = ServerRequestFactory::fromGlobals(); $request->getSession()->write('Webauthn2fa.User', $user); - $adapter = new RegisterAdapter($request); + $adapter = new RegisterAdapter($request, $UsersTable); $options = $adapter->getOptions(); $this->assertInstanceOf(PublicKeyCredentialCreationOptions::class, $options); $this->assertSame($options, $request->getSession()->read('Webauthn2fa.registerOptions')); diff --git a/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php b/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php index b95051275..81e1a84d2 100644 --- a/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php +++ b/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php @@ -25,12 +25,12 @@ public function testFindOneByCredentialId() { $UsersTable = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $user = $UsersTable->get('00000000-0000-0000-0000-000000000001'); - $repository = new UserCredentialSourceRepository($user); + $repository = new UserCredentialSourceRepository($user, $UsersTable); $credential = $repository->findOneByCredentialId('12b37486-9299-4331-ac33-85b2d985b6fe'); $this->assertInstanceOf(PublicKeyCredentialSource::class, $credential); //Not found id - $repository = new UserCredentialSourceRepository($user); + $repository = new UserCredentialSourceRepository($user, $UsersTable); $credential = $repository->findOneByCredentialId('some-testing-value'); $this->assertNull($credential); } @@ -50,7 +50,7 @@ public function testFindAllForUserEntity() $userId, // ID 'John Doe' // Display name ); - $repository = new UserCredentialSourceRepository($user); + $repository = new UserCredentialSourceRepository($user, $UsersTable); $credentials = $repository->findAllForUserEntity($userEntity); $this->assertCount(1, $credentials); $this->assertInstanceOf(PublicKeyCredentialSource::class, $credentials[0]); @@ -61,7 +61,7 @@ public function testFindAllForUserEntity() '00000000-0000-0000-0000-000000000004', // ID 'John Doe' // Display name ); - $repository = new UserCredentialSourceRepository($user); + $repository = new UserCredentialSourceRepository($user, $UsersTable); $credentials = $repository->findAllForUserEntity($userEntityInvalid); $this->assertEmpty($credentials); } @@ -91,16 +91,29 @@ public function testSaveCredentialSource() ]; $UsersTable = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $user = $UsersTable->get($userId); - + $firstKey = key($user->additional_data['webauthn_credentials']); $userEntity = new PublicKeyCredentialUserEntity( 'john.doe', // Username $userId, // ID 'John Doe' // Display name ); $publicKey = PublicKeyCredentialSource::createFromArray($credentialData); - $repository = new UserCredentialSourceRepository($user); + $repository = new UserCredentialSourceRepository($user, $UsersTable); $repository->saveCredentialSource($publicKey); $credentials = $repository->findAllForUserEntity($userEntity); $this->assertCount(2, $credentials); + $userAfter = $UsersTable->get($user->id); + $this->assertArrayHasKey( + '12b37486-9299-4331-ac33-85b2d985b6fe', + $userAfter->additional_data['webauthn_credentials'] + ); + $this->assertArrayHasKey( + $firstKey, + $userAfter->additional_data['webauthn_credentials'] + ); + $this->assertCount( + 2, + $userAfter->additional_data['webauthn_credentials'] + ); } } From 659e83c7f9040526dd62733277f92fbb0a5fe0ba Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Dec 2021 09:13:02 -0300 Subject: [PATCH 665/685] Added method to check if has credential --- src/Webauthn/BaseAdapter.php | 13 ++++++++++++- tests/TestCase/Webauthn/RegisterAdapterTest.php | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Webauthn/BaseAdapter.php b/src/Webauthn/BaseAdapter.php index 6d37ab6dd..795806f52 100644 --- a/src/Webauthn/BaseAdapter.php +++ b/src/Webauthn/BaseAdapter.php @@ -53,6 +53,7 @@ public function __construct(ServerRequest $request, ?UsersTable $usersTable = nu $this->user, $usersTable ); + $this->server = new Server( $rpEntity, $this->repository @@ -65,7 +66,7 @@ public function __construct(ServerRequest $request, ?UsersTable $usersTable = nu */ protected function getUserEntity(): PublicKeyCredentialUserEntity { - $user = $this->request->getSession()->read('Webauthn2fa.User'); + $user = $this->getUser(); return new PublicKeyCredentialUserEntity( $user->webauthn_username ?? $user->username, @@ -81,4 +82,14 @@ public function getUser() { return $this->user; } + + /** + * @return bool + */ + public function hasCredential(): bool + { + return (bool)$this->repository->findAllForUserEntity( + $this->getUserEntity() + ); + } } diff --git a/tests/TestCase/Webauthn/RegisterAdapterTest.php b/tests/TestCase/Webauthn/RegisterAdapterTest.php index 08e4a817f..b85c8ec0b 100644 --- a/tests/TestCase/Webauthn/RegisterAdapterTest.php +++ b/tests/TestCase/Webauthn/RegisterAdapterTest.php @@ -33,6 +33,7 @@ public function testGetOptions() $request = ServerRequestFactory::fromGlobals(); $request->getSession()->write('Webauthn2fa.User', $user); $adapter = new RegisterAdapter($request, $UsersTable); + $this->assertFalse($adapter->hasCredential()); $options = $adapter->getOptions(); $this->assertInstanceOf(PublicKeyCredentialCreationOptions::class, $options); $this->assertSame($options, $request->getSession()->read('Webauthn2fa.registerOptions')); @@ -78,7 +79,7 @@ public function testGetOptions() $key = key($credentialsList); $this->assertIsString($key); $this->assertTrue(isset($credentialsList[$key]['publicKeyCredentialId'])); - + $this->assertTrue($adapter->hasCredential()); //Invalid challenge without mock $adapter = new RegisterAdapter($request); $this->expectException(\Assert\InvalidArgumentException::class); From 766239c1895347f844cc98a0cde46a411b7cd50a Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Dec 2021 10:12:20 -0300 Subject: [PATCH 666/685] Persist webauthn credential --- config/users.php | 6 ++++++ .../Repository/UserCredentialSourceRepository.php | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/config/users.php b/config/users.php index e927ea4d4..3eb74302a 100644 --- a/config/users.php +++ b/config/users.php @@ -118,6 +118,12 @@ 'enabled' => false, 'checker' => \CakeDC\Auth\Authentication\DefaultU2fAuthenticationChecker::class, ], + 'Webauthn2fa' => [ + 'enabled' => false, + 'appName' => null,//App must set a valid name here + 'id' => null,//default value is the current domain + 'checker' => \CakeDC\Auth\Authentication\DefaultWebauthn2fAuthenticationChecker::class, + ], // default configuration used to auto-load the Auth Component, override to change the way Auth works 'Auth' => [ 'Authentication' => [ diff --git a/src/Webauthn/Repository/UserCredentialSourceRepository.php b/src/Webauthn/Repository/UserCredentialSourceRepository.php index 27432fa63..c18c42596 100644 --- a/src/Webauthn/Repository/UserCredentialSourceRepository.php +++ b/src/Webauthn/Repository/UserCredentialSourceRepository.php @@ -5,6 +5,7 @@ use Base64Url\Base64Url; use Cake\Datasource\EntityInterface; +use CakeDC\Users\Model\Table\UsersTable; use Webauthn\PublicKeyCredentialSource; use Webauthn\PublicKeyCredentialSourceRepository; use Webauthn\PublicKeyCredentialUserEntity; @@ -15,13 +16,19 @@ class UserCredentialSourceRepository implements PublicKeyCredentialSourceReposit * @var EntityInterface */ private $user; + /** + * @var UsersTable|null + */ + private $usersTable; /** * @param EntityInterface $user + * @param UsersTable|null $usersTable */ - public function __construct(EntityInterface $user) + public function __construct(EntityInterface $user, ?UsersTable $usersTable = null) { $this->user = $user; + $this->usersTable = $usersTable; } /** @@ -65,5 +72,6 @@ public function saveCredentialSource(PublicKeyCredentialSource $publicKeyCredent $credentials[$id] = json_decode(json_encode($publicKeyCredentialSource), true); $this->user['additional_data'] = $this->user['additional_data'] ?? []; $this->user['additional_data']['webauthn_credentials'] = $credentials; + $this->usersTable->saveOrFail($this->user); } } From 2d125d4ccbf2c589c0e5e513f058c1da78f45dff Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Dec 2021 12:02:17 -0300 Subject: [PATCH 667/685] Added actions to handle webauthn2fa --- config/permissions.php | 7 +- src/Controller/Traits/Webauthn2faTrait.php | 129 +++++ src/Controller/UsersController.php | 14 +- src/Utility/UsersUrl.php | 1 + templates/Users/webauthn2fa.php | 55 +++ .../Traits/Webauthn2faTraitTest.php | 458 ++++++++++++++++++ webroot/js/webauthn.js | 214 ++++++++ 7 files changed, 876 insertions(+), 2 deletions(-) create mode 100644 src/Controller/Traits/Webauthn2faTrait.php create mode 100644 templates/Users/webauthn2fa.php create mode 100644 tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php create mode 100644 webroot/js/webauthn.js diff --git a/config/permissions.php b/config/permissions.php index 3e9bc2369..5c52467fb 100644 --- a/config/permissions.php +++ b/config/permissions.php @@ -79,6 +79,11 @@ 'u2fRegisterFinish', 'u2fAuthenticate', 'u2fAuthenticateFinish', + 'webauthn2fa', + 'webauthn2faRegister', + 'webauthn2faRegisterOptions', + 'webauthn2faAuthenticate', + 'webauthn2faAuthenticateOptions', ], 'bypassAuth' => true, ], @@ -134,6 +139,6 @@ 'controller' => '*', 'action' => '*', 'bypassAuth' => true, - ], + ], ] ]; diff --git a/src/Controller/Traits/Webauthn2faTrait.php b/src/Controller/Traits/Webauthn2faTrait.php new file mode 100644 index 000000000..eedaf88e6 --- /dev/null +++ b/src/Controller/Traits/Webauthn2faTrait.php @@ -0,0 +1,129 @@ +getWebauthn2faRegisterAdapter(); + $user = $adapter->getUser(); + $this->set('isRegister', !$adapter->hasCredential()); + $this->set('username', $user->webauthn_username ?? $user->username); + } + + /** + * Action to provide register options to frontend (from js requests) + * + * @return \Cake\Http\Response + */ + public function webauthn2faRegisterOptions() + { + $adapter = $this->getWebauthn2faRegisterAdapter(); + + return $this->getResponse()->withStringBody(json_encode($adapter->getOptions())); + } + + /** + * Action to verify and save the new credential based on the webauthn register response. + * + * @return \Cake\Http\Response + * @throws \Throwable + */ + public function webauthn2faRegister(): \Cake\Http\Response + { + try { + $this->getWebauthn2faRegisterAdapter()->verifyResponse(); + + return $this->getResponse()->withStringBody(json_encode(['success' => true])); + } catch (\Throwable $e) { + $user = $this->request->getSession()->read('Webauthn2fa.User'); + Log::debug(__('Register error with webauthn for user id: {0}', $user['id'] ?? 'empty')); + throw $e; + } + } + + /** + * Action to provide authenticate options to frontend (from js requests) + * + * @return \Cake\Http\Response + */ + public function webauthn2faAuthenticateOptions(): \Cake\Http\Response + { + $adapter = $this->getWebauthn2faAuthenticateAdapter(); + + return $this->getResponse()->withStringBody( + json_encode($adapter->getOptions()) + ); + } + + /** + * Action to authenticate user based on the webauthn authenticate response. + * + * @return \Cake\Http\Response + * @throws \Throwable + */ + public function webauthn2faAuthenticate(): \Cake\Http\Response + { + try { + $adapter = $this->getWebauthn2faAuthenticateAdapter(); + $adapter->verifyResponse(); + $redirectUrl = Configure::read('Auth.AuthenticationComponent.loginAction') + [ + '?' => $this->getRequest()->getQueryParams() + ]; + $this->getRequest()->getSession()->delete('Webauthn2fa'); + $this->getRequest()->getSession()->write( + TwoFactorAuthenticator::USER_SESSION_KEY, + $adapter->getUser() + ); + + return $this->getResponse()->withStringBody(json_encode([ + 'success' => true, + 'redirectUrl' => Router::url($redirectUrl) + ])); + } catch (\Throwable $e) { + $user = $this->request->getSession()->read('Webauthn2fa.User'); + Log::debug(__('Register error with webauthn for user id: {0}', $user['id'] ?? 'empty')); + throw $e; + } + } + + /** + * @return RegisterAdapter + */ + protected function getWebauthn2faRegisterAdapter(): RegisterAdapter + { + return new RegisterAdapter($this->getRequest(), $this->getUsersTable()); + } + + /** + * @return AuthenticateAdapter + */ + protected function getWebauthn2faAuthenticateAdapter(): AuthenticateAdapter + { + return new AuthenticateAdapter($this->getRequest()); + } +} diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 6cffb4590..096bbc9c1 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -22,6 +22,7 @@ use CakeDC\Users\Controller\Traits\SimpleCrudTrait; use CakeDC\Users\Controller\Traits\SocialTrait; use CakeDC\Users\Controller\Traits\U2fTrait; +use CakeDC\Users\Controller\Traits\Webauthn2faTrait; /** * Users Controller @@ -40,6 +41,7 @@ class UsersController extends AppController use SimpleCrudTrait; use SocialTrait; use U2fTrait; + use Webauthn2faTrait; /** * Initialize @@ -52,7 +54,17 @@ public function initialize(): void if ($this->components()->has('Security')) { $this->Security->setConfig( 'unlockedActions', - ['login', 'u2fRegister', 'u2fRegisterFinish', 'u2fAuthenticate', 'u2fAuthenticateFinish'] + [ + 'login', + 'u2fRegister', + 'u2fRegisterFinish', + 'u2fAuthenticate', + 'u2fAuthenticateFinish', + 'webauthn2faRegister', + 'webauthn2faRegisterOptions', + 'webauthn2faAuthenticate', + 'webauthn2faAuthenticateOptions', + ] ); } } diff --git a/src/Utility/UsersUrl.php b/src/Utility/UsersUrl.php index 96d05151a..935e4cb0f 100644 --- a/src/Utility/UsersUrl.php +++ b/src/Utility/UsersUrl.php @@ -124,6 +124,7 @@ private static function getDefaultConfigUrls() 'Users.Profile.route' => static::actionUrl('profile'), 'OneTimePasswordAuthenticator.verifyAction' => static::actionUrl('verify'), 'U2f.startAction' => static::actionUrl('u2f'), + 'Webauthn2fa.startAction' => static::actionUrl('webauthn2fa'), 'Auth.AuthenticationComponent.loginAction' => $loginAction, 'Auth.AuthenticationComponent.logoutRedirect' => $loginAction, 'Auth.Authenticators.Form.loginUrl' => $loginAction, diff --git a/templates/Users/webauthn2fa.php b/templates/Users/webauthn2fa.php new file mode 100644 index 000000000..dab4aba4a --- /dev/null +++ b/templates/Users/webauthn2fa.php @@ -0,0 +1,55 @@ +Html->script('CakeDC/Users.webauthn.js', ['block' => true]); +$this->assign('title', __('Two-factor authentication')); +?> +
+
+
+
+ + Flash->render('auth') ?> + Flash->render() ?> +
+ + +

Html->link( + __('Reload'), + ['action' => 'webauthn2fa'], + ['class' => 'btn btn-primary'] + )?>

+
+
+
+
+
+ $this->Url->build(['action' => 'webauthn2faAuthenticate']), + 'authenticateOptionsUrl' => $this->Url->build(['action' => 'webauthn2faAuthenticateOptions']), + 'registerActionUrl' => $this->Url->build(['action' => 'webauthn2faRegister']), + 'registerOptionsUrl' => $this->Url->build(['action' => 'webauthn2faRegisterOptions']), + 'isRegister' => $isRegister, + 'username' => h($username), + 'registerElemId' => 'webauthn2faRegisterInfo', + 'authenticateElemId' => 'webauthn2faAuthenticateInfo', +]; +$this->Html->scriptStart(['block' => true]); +?> +setTimeout(function() { + Webauthn2faHelper.run(); +}, 1000); +Html->scriptEnd();?> diff --git a/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php b/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php new file mode 100644 index 000000000..fab3eefc9 --- /dev/null +++ b/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php @@ -0,0 +1,458 @@ +traitClassName = 'CakeDC\Users\Controller\UsersController'; + $this->traitMockMethods = ['dispatchEvent', 'isStopped', 'redirect', 'getUsersTable', 'set', 'createU2fLib', 'getData', 'getU2fAuthenticationChecker']; + + parent::setUp(); + + $request = new ServerRequest(); + $this->Trait->setRequest($request); + Configure::write('Webauthn2fa.enabled', true); + Configure::write('Webauthn2fa.appName', 'ACME Webauthn Server'); + Configure::write('Webauthn2fa.id', 'localhost'); + + } + + /** + * 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 + ->getRequest() + ->expects($this->any()) + ->method('getSession') + ->willReturn($session); + + return $session; + } + + /** + * Test webauthn2fa method when requires register + * + * @return void + */ + public function testWebauthn2faIsRegister() + { + $request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->setMethods(['getSession', 'is']) + ->getMock(); + $this->Trait->setRequest($request); + $request->expects($this->any()) + ->method('is') + ->with( + $this->equalTo('ssl') + )->will($this->returnValue(true)); + + $table = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users'); + $user = $table->get('00000000-0000-0000-0000-000000000002'); + $this->_mockSession([ + 'Webauthn2fa.User' => $user, + ]); + $this->Trait->expects($this->at(1)) + ->method('set') + ->with( + $this->equalTo('isRegister'), + $this->equalTo(true) + ); + $this->Trait->expects($this->at(2)) + ->method('set') + ->with( + $this->equalTo('username'), + $this->equalTo('user-2') + ); + $this->Trait->webauthn2fa(); + $this->assertSame( + $user, + $this->Trait->getRequest()->getSession()->read('Webauthn2fa.User') + ); + } + + /** + * Test webauthn2fa method when DON'T require register + * + * @return void + */ + public function testWebauthn2faDontRequireRegister() + { + $request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->setMethods(['getSession', 'is']) + ->getMock(); + $this->Trait->setRequest($request); + $request->expects($this->any()) + ->method('is') + ->with( + $this->equalTo('ssl') + )->will($this->returnValue(true)); + + $table = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users'); + $user = $table->get('00000000-0000-0000-0000-000000000001'); + $this->_mockSession([ + 'Webauthn2fa.User' => $user, + ]); + $this->Trait->expects($this->at(1)) + ->method('set') + ->with( + $this->equalTo('isRegister'), + $this->equalTo(false) + ); + $this->Trait->expects($this->at(2)) + ->method('set') + ->with( + $this->equalTo('username'), + $this->equalTo('user-1') + ); + $this->Trait->webauthn2fa(); + $this->assertSame( + $user, + $this->Trait->getRequest()->getSession()->read('Webauthn2fa.User') + ); + } + + /** + * Test webauthn2faRegisterOptions method + * + * @return void + */ + public function testWebauthn2faRegisterOptions() + { + $request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->setMethods(['getSession', 'is']) + ->getMock(); + $this->Trait->setRequest($request); + $request->expects($this->any()) + ->method('is') + ->with( + $this->equalTo('ssl') + )->will($this->returnValue(true)); + + $table = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users'); + $user = $table->get('00000000-0000-0000-0000-000000000002'); + $this->_mockSession([ + 'Webauthn2fa.User' => $user, + ]); + + $response = $this->Trait->webauthn2faRegisterOptions(); + $data = json_decode((string)$response->getBody(), true); + $this->assertArrayHasKey('rp', $data); + $this->assertArrayHasKey('user', $data); + $this->assertSame('user-2', $data['user']['name']); + $this->assertSame( + $user, + $this->Trait->getRequest()->getSession()->read('Webauthn2fa.User') + ); + } + + /** + * Test webauthn2faRegisterOptions method + * + * @return void + */ + public function testWebauthn2faRegister() + { + $table = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users'); + $user = $table->get('00000000-0000-0000-0000-000000000002'); + $request = ServerRequestFactory::fromGlobals(); + $request->getSession()->write('Webauthn2fa.User', $user); + + $this->Trait->setRequest($request); + $adapter = $this->getMockBuilder(RegisterAdapter::class) + ->onlyMethods(['verifyResponse']) + ->setConstructorArgs([$request]) + ->getMock(); + $publicKeyCredentialId = '12b37486-9299-4331-ac33-85b2d985b6fe'; + $userId = '00000000-0000-0000-0000-000000000002'; + $credentialData = [ + 'publicKeyCredentialId' => $publicKeyCredentialId, + 'type' => 'public-key', + 'transports' => [], + 'attestationType' => 'none', + 'trustPath' => [ + 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + ], + 'aaguid' => '00000000-0000-0000-0000-000000000000', + 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-YYYYYYYYYYY'), + 'userHandle' => Base64Url::encode($userId), + 'counter' => 191, + 'otherUI' => null + ]; + $credential = PublicKeyCredentialSource::createFromArray($credentialData); + $adapter->expects($this->once()) + ->method('verifyResponse') + ->willReturn($credential); + + $traitMockMethods = array_unique(array_merge(['getUsersTable', 'getWebauthn2faRegisterAdapter'], $this->traitMockMethods)); + $this->Trait = $this->getMockBuilder($this->traitClassName) + ->setMethods($traitMockMethods) + ->getMock(); + $this->Trait->expects($this->once()) + ->method('getWebauthn2faRegisterAdapter') + ->willReturn($adapter); + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($this->table)); + $data = '{"id":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","rawId":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","response":{"clientDataJSON":"eyJjaGFsbGVuZ2UiOiJOeHlab3B3VktiRmw3RW5uTWFlXzVGbmlyN1FKN1FXcDFVRlVLakZIbGZrIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9","attestationObject":"o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIgVzzvX3Nyp_g9j9f2B-tPWy6puW01aZHI8RXjwqfDjtQCIQDLsdniGPO9iKr7tdgVV-FnBYhvzlZLG3u28rVt10YXfGN4NWOBWQJOMIICSjCCATKgAwIBAgIEVxb3wDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowLDEqMCgGA1UEAwwhWXViaWNvIFUyRiBFRSBTZXJpYWwgMjUwNTY5MjI2MTc2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZNkcVNbZV43TsGB4TEY21UijmDqvNSfO6y3G4ytnnjP86ehjFK28-FdSGy9MSZ-Ur3BVZb4iGVsptk5NrQ3QYqM7MDkwIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjUwEwYLKwYBBAGC5RwCAQEEBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAHibGMqbpNt2IOL4i4z96VEmbSoid9Xj--m2jJqg6RpqSOp1TO8L3lmEA22uf4uj_eZLUXYEw6EbLm11TUo3Ge-odpMPoODzBj9aTKC8oDFPfwWj6l1O3ZHTSma1XVyPqG4A579f3YAjfrPbgj404xJns0mqx5wkpxKlnoBKqo1rqSUmonencd4xanO_PHEfxU0iZif615Xk9E4bcANPCfz-OLfeKXiT-1msixwzz8XGvl2OTMJ_Sh9G9vhE-HjAcovcHfumcdoQh_WM445Za6Pyn9BZQV3FCqMviRR809sIATfU5lu86wu_5UGIGI7MFDEYeVGSqzpzh6mlcn8QSIZoYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAsV2gIUlPIHzZnNIlQdz5zvbKtpFz_WY-8ZfxOgTyy7f3Ffbolyp3fUtSQo5LfoUgBaBaXqK0wqqYO-u6FrrLApQECAyYgASFYIPr9-YH8DuBsOnaI3KJa0a39hyxh9LDtHErNvfQSyxQsIlgg4rAuQQ5uy4VXGFbkiAt0uwgJJodp-DymkoBcrGsLtkI"},"type":"public-key"}'; + $request = $request->withParsedBody( + json_decode($data, true) + ); + $this->Trait->setRequest($request); + $response = $this->Trait->webauthn2faRegister(); + $this->assertEquals('{"success":true}', (string)$response->getBody()); + } + + /** + * Test webauthn2faRegisterOptions method + * + * @return void + */ + public function testWebauthn2faRegisterError() + { + $table = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users'); + $user = $table->get('00000000-0000-0000-0000-000000000002'); + $request = ServerRequestFactory::fromGlobals(); + $request->getSession()->write('Webauthn2fa.User', $user); + + $this->Trait->setRequest($request); + $adapter = $this->getMockBuilder(RegisterAdapter::class) + ->onlyMethods(['verifyResponse']) + ->setConstructorArgs([$request]) + ->getMock(); + + $adapter->expects($this->once()) + ->method('verifyResponse') + ->willThrowException(new \Exception('Testing error exception for webauthn2faRegister')); + + $traitMockMethods = array_unique(array_merge(['getUsersTable', 'getWebauthn2faRegisterAdapter'], $this->traitMockMethods)); + $this->Trait = $this->getMockBuilder($this->traitClassName) + ->setMethods($traitMockMethods) + ->getMock(); + $this->Trait->expects($this->once()) + ->method('getWebauthn2faRegisterAdapter') + ->willReturn($adapter); + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($this->table)); + $data = '{"id":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","rawId":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA","response":{"clientDataJSON":"eyJjaGFsbGVuZ2UiOiJOeHlab3B3VktiRmw3RW5uTWFlXzVGbmlyN1FKN1FXcDFVRlVLakZIbGZrIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9","attestationObject":"o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIgVzzvX3Nyp_g9j9f2B-tPWy6puW01aZHI8RXjwqfDjtQCIQDLsdniGPO9iKr7tdgVV-FnBYhvzlZLG3u28rVt10YXfGN4NWOBWQJOMIICSjCCATKgAwIBAgIEVxb3wDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowLDEqMCgGA1UEAwwhWXViaWNvIFUyRiBFRSBTZXJpYWwgMjUwNTY5MjI2MTc2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZNkcVNbZV43TsGB4TEY21UijmDqvNSfO6y3G4ytnnjP86ehjFK28-FdSGy9MSZ-Ur3BVZb4iGVsptk5NrQ3QYqM7MDkwIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjUwEwYLKwYBBAGC5RwCAQEEBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAHibGMqbpNt2IOL4i4z96VEmbSoid9Xj--m2jJqg6RpqSOp1TO8L3lmEA22uf4uj_eZLUXYEw6EbLm11TUo3Ge-odpMPoODzBj9aTKC8oDFPfwWj6l1O3ZHTSma1XVyPqG4A579f3YAjfrPbgj404xJns0mqx5wkpxKlnoBKqo1rqSUmonencd4xanO_PHEfxU0iZif615Xk9E4bcANPCfz-OLfeKXiT-1msixwzz8XGvl2OTMJ_Sh9G9vhE-HjAcovcHfumcdoQh_WM445Za6Pyn9BZQV3FCqMviRR809sIATfU5lu86wu_5UGIGI7MFDEYeVGSqzpzh6mlcn8QSIZoYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAsV2gIUlPIHzZnNIlQdz5zvbKtpFz_WY-8ZfxOgTyy7f3Ffbolyp3fUtSQo5LfoUgBaBaXqK0wqqYO-u6FrrLApQECAyYgASFYIPr9-YH8DuBsOnaI3KJa0a39hyxh9LDtHErNvfQSyxQsIlgg4rAuQQ5uy4VXGFbkiAt0uwgJJodp-DymkoBcrGsLtkI"},"type":"public-key"}'; + $request = $request->withParsedBody( + json_decode($data, true) + ); + $this->Trait->setRequest($request); + $this->expectException(\Exception::class); + $this->expectErrorMessage('Testing error exception for webauthn2faRegister'); + $this->Trait->webauthn2faRegister(); + } + + + /** + * Test webauthn2faAuthenticateOptions + * + * @return void + */ + public function testWebauthn2faAuthenticateOptions() + { + $request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->setMethods(['getSession', 'is']) + ->getMock(); + $this->Trait->setRequest($request); + $request->expects($this->any()) + ->method('is') + ->with( + $this->equalTo('ssl') + )->will($this->returnValue(true)); + + $table = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users'); + $user = $table->get('00000000-0000-0000-0000-000000000001'); + $this->_mockSession([ + 'Webauthn2fa.User' => $user, + ]); + + $response = $this->Trait->webauthn2faAuthenticateOptions(); + $data = json_decode((string)$response->getBody(), true); + $this->assertArrayHasKey('challenge', $data); + $this->assertArrayHasKey('userVerification', $data); + $this->assertArrayHasKey('allowCredentials', $data); + $expectedCredentials = [ + [ + 'type' => 'public-key', + 'id' => '12b37486-9299-4331-ac33-85b2d985b6fe', + ], + ]; + $this->assertEquals($expectedCredentials, $data['allowCredentials']); + $this->assertSame( + $user, + $this->Trait->getRequest()->getSession()->read('Webauthn2fa.User') + ); + } + + /** + * Test webauthn2faAuthenticateOptions method + * + * @return void + */ + public function testWebauthn2faAuthenticate() + { + $table = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users'); + $user = $table->get('00000000-0000-0000-0000-000000000002'); + $request = ServerRequestFactory::fromGlobals(); + $request->getSession()->write('Webauthn2fa.User', $user); + + $this->Trait->setRequest($request); + $adapter = $this->getMockBuilder(AuthenticateAdapter::class) + ->onlyMethods(['verifyResponse']) + ->setConstructorArgs([$request]) + ->getMock(); + $publicKeyCredentialId = '12b37486-9299-4331-ac33-85b2d985b6fe'; + $userId = '00000000-0000-0000-0000-000000000002'; + $credentialData = [ + 'publicKeyCredentialId' => $publicKeyCredentialId, + 'type' => 'public-key', + 'transports' => [], + 'attestationType' => 'none', + 'trustPath' => [ + 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + ], + 'aaguid' => '00000000-0000-0000-0000-000000000000', + 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-YYYYYYYYYYY'), + 'userHandle' => Base64Url::encode($userId), + 'counter' => 191, + 'otherUI' => null + ]; + $credential = PublicKeyCredentialSource::createFromArray($credentialData); + $adapter->expects($this->once()) + ->method('verifyResponse') + ->willReturn($credential); + + $traitMockMethods = array_unique(array_merge(['getUsersTable', 'getWebauthn2faAuthenticateAdapter'], $this->traitMockMethods)); + $this->Trait = $this->getMockBuilder($this->traitClassName) + ->setMethods($traitMockMethods) + ->getMock(); + $this->Trait->expects($this->once()) + ->method('getWebauthn2faAuthenticateAdapter') + ->willReturn($adapter); + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($this->table)); + $this->Trait->setRequest($request); + $response = $this->Trait->webauthn2faAuthenticate(); + $expected = [ + 'success' => true, + 'redirectUrl' => '/login', + ]; + $actual = json_decode((string)$response->getBody(), true); + $this->assertEquals($expected, $actual); + + $this->assertNull( + $this->Trait->getRequest()->getSession()->read('Webauthn2fa.User') + ); + $userSession = $this->Trait->getRequest()->getSession()->read('TwoFactorAuthenticator.User'); + $this->assertInstanceOf( + User::class, + $userSession + ); + $this->assertEquals($userSession->toArray(), $user->toArray()); + } + + /** + * Test webauthn2faAuthenticateOptions method + * + * @return void + */ + public function testWebauthn2faAuthenticateError() + { + $table = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users'); + $user = $table->get('00000000-0000-0000-0000-000000000002'); + $request = ServerRequestFactory::fromGlobals(); + $request->getSession()->write('Webauthn2fa.User', $user); + + $this->Trait->setRequest($request); + $adapter = $this->getMockBuilder(AuthenticateAdapter::class) + ->onlyMethods(['verifyResponse']) + ->setConstructorArgs([$request]) + ->getMock(); + + $adapter->expects($this->once()) + ->method('verifyResponse') + ->willThrowException(new \Exception('Test exception error for webauthn2faAuthenticate')); + + $traitMockMethods = array_unique(array_merge(['getUsersTable', 'getWebauthn2faAuthenticateAdapter'], $this->traitMockMethods)); + $this->Trait = $this->getMockBuilder($this->traitClassName) + ->setMethods($traitMockMethods) + ->getMock(); + $this->Trait->expects($this->once()) + ->method('getWebauthn2faAuthenticateAdapter') + ->willReturn($adapter); + $this->Trait->expects($this->any()) + ->method('getUsersTable') + ->will($this->returnValue($this->table)); + $this->Trait->setRequest($request); + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Test exception error for webauthn2faAuthenticate'); + $this->Trait->webauthn2faAuthenticate(); + } +} diff --git a/webroot/js/webauthn.js b/webroot/js/webauthn.js new file mode 100644 index 000000000..45f9e9c22 --- /dev/null +++ b/webroot/js/webauthn.js @@ -0,0 +1,214 @@ +//Source code based on https://github.com/web-auth/webauthn-helper +// Predefined fetch function +const fetchEndpoint = (data, url, header) => { + return fetch( + url, + { + method: 'POST', + credentials: 'same-origin', + redirect: 'error', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + ...header + }, + body: JSON.stringify(data), + } + ); +} + +// Decodes a Base64Url string +const base64UrlDecode = (input) => { + input = input + .replace(/-/g, '+') + .replace(/_/g, '/'); + + const pad = input.length % 4; + if (pad) { + if (pad === 1) { + throw new Error('InvalidLengthError: Input base64url string is the wrong length to determine padding'); + } + input += new Array(5-pad).join('='); + } + + return window.atob(input); +}; + +// Converts an array of bytes into a Base64Url string +const arrayToBase64String = (a) => btoa(String.fromCharCode(...a)); + +// Prepares the public key options object returned by the Webauthn Framework +const preparePublicKeyOptions = publicKey => { + //Convert challenge from Base64Url string to Uint8Array + publicKey.challenge = Uint8Array.from( + base64UrlDecode(publicKey.challenge), + c => c.charCodeAt(0) + ); + + //Convert the user ID from Base64 string to Uint8Array + if (publicKey.user !== undefined) { + publicKey.user = { + ...publicKey.user, + id: Uint8Array.from( + window.atob(publicKey.user.id), + c => c.charCodeAt(0) + ), + }; + } + + //If excludeCredentials is defined, we convert all IDs to Uint8Array + if (publicKey.excludeCredentials !== undefined) { + publicKey.excludeCredentials = publicKey.excludeCredentials.map( + data => { + return { + ...data, + id: Uint8Array.from( + base64UrlDecode(data.id), + c => c.charCodeAt(0) + ), + }; + } + ); + } + + if (publicKey.allowCredentials !== undefined) { + publicKey.allowCredentials = publicKey.allowCredentials.map( + data => { + return { + ...data, + id: Uint8Array.from( + base64UrlDecode(data.id), + c => c.charCodeAt(0) + ), + }; + } + ); + } + + return publicKey; +}; + +// Prepares the public key credentials object returned by the authenticator +const preparePublicKeyCredentials = data => { + const publicKeyCredential = { + id: data.id, + type: data.type, + rawId: arrayToBase64String(new Uint8Array(data.rawId)), + response: { + clientDataJSON: arrayToBase64String( + new Uint8Array(data.response.clientDataJSON) + ), + }, + }; + + if (data.response.attestationObject !== undefined) { + publicKeyCredential.response.attestationObject = arrayToBase64String( + new Uint8Array(data.response.attestationObject) + ); + } + + if (data.response.authenticatorData !== undefined) { + publicKeyCredential.response.authenticatorData = arrayToBase64String( + new Uint8Array(data.response.authenticatorData) + ); + } + + if (data.response.signature !== undefined) { + publicKeyCredential.response.signature = arrayToBase64String( + new Uint8Array(data.response.signature) + ); + } + + if (data.response.userHandle !== undefined) { + publicKeyCredential.response.userHandle = arrayToBase64String( + new Uint8Array(data.response.userHandle) + ); + } + + return publicKeyCredential; +}; + +const useLogin = ({actionUrl = '/login', actionHeader = {}, optionsUrl = '/login/options'}, optionsHeader = {}) => { + return async (data) => { + const optionsResponse = await fetchEndpoint(data, optionsUrl, optionsHeader); + const json = await optionsResponse.json(); + const publicKey = preparePublicKeyOptions(json); + const credentials = await navigator.credentials.get({publicKey}); + const publicKeyCredential = preparePublicKeyCredentials(credentials); + const actionResponse = await fetchEndpoint(publicKeyCredential, actionUrl, actionHeader); + if (! actionResponse.ok) { + throw actionResponse; + } + const responseBody = await actionResponse.text(); + + return responseBody !== '' ? JSON.parse(responseBody) : responseBody; + }; +}; + + +const useRegistration = ({actionUrl = '/register', actionHeader = {}, optionsUrl = '/register/options'}, optionsHeader = {}) => { + return async (data) => { + const optionsResponse = await fetchEndpoint(data, optionsUrl, optionsHeader); + const json = await optionsResponse.json(); + const publicKey = preparePublicKeyOptions(json); + const credentials = await navigator.credentials.create({publicKey}); + const publicKeyCredential = preparePublicKeyCredentials(credentials); + const actionResponse = await fetchEndpoint(publicKeyCredential, actionUrl, actionHeader); + if (! actionResponse.ok) { + throw actionResponse; + } + const responseBody = await actionResponse.text(); + + return responseBody !== '' ? JSON.parse(responseBody) : responseBody; + }; +}; + +var Webauthn2faHelper = { + toggleElem: function(options) { + console.log({options}); + document.getElementById(options.authenticateElemId).style.display = options.isRegister ? 'none' : 'block'; + document.getElementById(options.registerElemId).style.display = options.isRegister ? 'block' : 'none'; + }, + authenticate: function(options) { + var authenticate = useLogin({ + actionUrl: options.authenticateActionUrl, + optionsUrl: options.authenticateOptionsUrl + }); + authenticate({ + username: options.username + }) + .then(function (response) { + window.location.href = response.redirectUrl; + }) + .catch((error) => { + window.alert('Authentication failure'); + }) + }, + register: function(options) { + var register = useRegistration({ + actionUrl: options.registerActionUrl, + optionsUrl: options.registerOptionsUrl + }); + + return register({ + username: options.username, + }) + .catch((error) => { + window.alert('Registration failed'); + }); + }, + run: function(options) { + Webauthn2faHelper.toggleElem(options); + if (options.isRegister) { + return Webauthn2faHelper.register(options) + .then(function (response) { + if (response && response.success) { + options.isRegister = false; + Webauthn2faHelper.toggleElem(options); + Webauthn2faHelper.authenticate(options); + } + }); + } + return Webauthn2faHelper.authenticate(options); + } +} From 7236f1a295a1c1e5637d8ac66bf375f461c926e2 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Dec 2021 12:12:57 -0300 Subject: [PATCH 668/685] fixing unit tests --- tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php b/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php index fab3eefc9..734020b5b 100644 --- a/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php +++ b/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php @@ -18,21 +18,17 @@ use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; use Cake\ORM\TableRegistry; -use CakeDC\Auth\Authentication\DefaultU2fAuthenticationChecker; use CakeDC\Users\Model\Entity\User; use CakeDC\Users\Webauthn\AuthenticateAdapter; use CakeDC\Users\Webauthn\RegisterAdapter; -use u2flib_server\RegisterRequest; -use u2flib_server\Registration; -use u2flib_server\U2F; use Webauthn\PublicKeyCredentialSource; /** - * Class U2fTraitTest + * Class Webauthn2faTraitTest * * @package App\Test\TestCase\Controller\Traits */ -class U2fTraitTest extends BaseTraitTest +class Webauthn2faTraitTest extends BaseTraitTest { /** * Fixtures From 4ff0180794807ada7e2b87469d3484be5a7ba38e Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Dec 2021 12:19:21 -0300 Subject: [PATCH 669/685] coding standard --- src/Webauthn/AuthenticateAdapter.php | 11 +++++++++++ src/Webauthn/RegisterAdapter.php | 17 +++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Webauthn/AuthenticateAdapter.php b/src/Webauthn/AuthenticateAdapter.php index 9b29d8d54..4ab4853ad 100644 --- a/src/Webauthn/AuthenticateAdapter.php +++ b/src/Webauthn/AuthenticateAdapter.php @@ -1,4 +1,15 @@ request->getSession()->read('Webauthn2fa.registerOptions'); $credential = $this->loadAndCheckAttestationResponse($options); $this->repository->saveCredentialSource($credential); @@ -40,7 +53,7 @@ public function verifyResponse(): \Webauthn\PublicKeyCredentialSource } /** - * @param $options + * @param \Webauthn\PublicKeyCredentialCreationOptions $options * @return \Webauthn\PublicKeyCredentialSource */ protected function loadAndCheckAttestationResponse($options): \Webauthn\PublicKeyCredentialSource From 8b5b4af669768a7a05308e85661d264f4fc8e8f7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Dec 2021 12:25:00 -0300 Subject: [PATCH 670/685] fixing cs --- src/Controller/Traits/Webauthn2faTrait.php | 8 +++---- src/Webauthn/AuthenticateAdapter.php | 8 +++---- src/Webauthn/BaseAdapter.php | 17 +++++++------- src/Webauthn/RegisterAdapter.php | 9 +++----- .../UserCredentialSourceRepository.php | 16 ++++++------- tests/Fixture/UsersFixture.php | 6 ++--- .../Traits/Webauthn2faTraitTest.php | 10 ++++---- .../Webauthn/AuthenticateAdapterTest.php | 7 +++--- .../TestCase/Webauthn/RegisterAdapterTest.php | 5 ++-- .../UserCredentialSourceRepositoryTest.php | 23 ++++++++++--------- 10 files changed, 52 insertions(+), 57 deletions(-) diff --git a/src/Controller/Traits/Webauthn2faTrait.php b/src/Controller/Traits/Webauthn2faTrait.php index eedaf88e6..95c6ad620 100644 --- a/src/Controller/Traits/Webauthn2faTrait.php +++ b/src/Controller/Traits/Webauthn2faTrait.php @@ -92,7 +92,7 @@ public function webauthn2faAuthenticate(): \Cake\Http\Response $adapter = $this->getWebauthn2faAuthenticateAdapter(); $adapter->verifyResponse(); $redirectUrl = Configure::read('Auth.AuthenticationComponent.loginAction') + [ - '?' => $this->getRequest()->getQueryParams() + '?' => $this->getRequest()->getQueryParams(), ]; $this->getRequest()->getSession()->delete('Webauthn2fa'); $this->getRequest()->getSession()->write( @@ -102,7 +102,7 @@ public function webauthn2faAuthenticate(): \Cake\Http\Response return $this->getResponse()->withStringBody(json_encode([ 'success' => true, - 'redirectUrl' => Router::url($redirectUrl) + 'redirectUrl' => Router::url($redirectUrl), ])); } catch (\Throwable $e) { $user = $this->request->getSession()->read('Webauthn2fa.User'); @@ -112,7 +112,7 @@ public function webauthn2faAuthenticate(): \Cake\Http\Response } /** - * @return RegisterAdapter + * @return \CakeDC\Users\Webauthn\RegisterAdapter */ protected function getWebauthn2faRegisterAdapter(): RegisterAdapter { @@ -120,7 +120,7 @@ protected function getWebauthn2faRegisterAdapter(): RegisterAdapter } /** - * @return AuthenticateAdapter + * @return \CakeDC\Users\Webauthn\AuthenticateAdapter */ protected function getWebauthn2faAuthenticateAdapter(): AuthenticateAdapter { diff --git a/src/Webauthn/AuthenticateAdapter.php b/src/Webauthn/AuthenticateAdapter.php index 4ab4853ad..592c9590a 100644 --- a/src/Webauthn/AuthenticateAdapter.php +++ b/src/Webauthn/AuthenticateAdapter.php @@ -19,7 +19,7 @@ class AuthenticateAdapter extends BaseAdapter { /** - * @return PublicKeyCredentialRequestOptions + * @return \Webauthn\PublicKeyCredentialRequestOptions */ public function getOptions(): PublicKeyCredentialRequestOptions { @@ -36,10 +36,10 @@ public function getOptions(): PublicKeyCredentialRequestOptions 'Webauthn2fa.authenticateOptions', $options ); + return $options; } - /** * Verify the registration response * @@ -53,8 +53,8 @@ public function verifyResponse(): \Webauthn\PublicKeyCredentialSource } /** - * @param $options - * @return PublicKeyCredentialSource + * @param \Webauthn\PublicKeyCredentialRequestOptions $options request options + * @return \Webauthn\PublicKeyCredentialSource */ protected function loadAndCheckAssertionResponse($options): PublicKeyCredentialSource { diff --git a/src/Webauthn/BaseAdapter.php b/src/Webauthn/BaseAdapter.php index 795806f52..4ee30b09c 100644 --- a/src/Webauthn/BaseAdapter.php +++ b/src/Webauthn/BaseAdapter.php @@ -1,9 +1,9 @@ repository ); - } /** - * @return PublicKeyCredentialUserEntity + * @return \Webauthn\PublicKeyCredentialUserEntity */ protected function getUserEntity(): PublicKeyCredentialUserEntity { diff --git a/src/Webauthn/RegisterAdapter.php b/src/Webauthn/RegisterAdapter.php index 36916de01..c28b0504a 100644 --- a/src/Webauthn/RegisterAdapter.php +++ b/src/Webauthn/RegisterAdapter.php @@ -18,7 +18,7 @@ class RegisterAdapter extends BaseAdapter { /** - * @return PublicKeyCredentialCreationOptions + * @return \Webauthn\PublicKeyCredentialCreationOptions */ public function getOptions(): PublicKeyCredentialCreationOptions { @@ -34,7 +34,6 @@ public function getOptions(): PublicKeyCredentialCreationOptions return $options; } - /** * Verify the registration response * @@ -42,9 +41,6 @@ public function getOptions(): PublicKeyCredentialCreationOptions */ public function verifyResponse(): \Webauthn\PublicKeyCredentialSource { - /** - * - */ $options = $this->request->getSession()->read('Webauthn2fa.registerOptions'); $credential = $this->loadAndCheckAttestationResponse($options); $this->repository->saveCredentialSource($credential); @@ -53,7 +49,7 @@ public function verifyResponse(): \Webauthn\PublicKeyCredentialSource } /** - * @param \Webauthn\PublicKeyCredentialCreationOptions $options + * @param \Webauthn\PublicKeyCredentialCreationOptions $options creation options * @return \Webauthn\PublicKeyCredentialSource */ protected function loadAndCheckAttestationResponse($options): \Webauthn\PublicKeyCredentialSource @@ -63,6 +59,7 @@ protected function loadAndCheckAttestationResponse($options): \Webauthn\PublicKe $options, $this->request ); + return $credential; } } diff --git a/src/Webauthn/Repository/UserCredentialSourceRepository.php b/src/Webauthn/Repository/UserCredentialSourceRepository.php index c18c42596..ecda3cbb0 100644 --- a/src/Webauthn/Repository/UserCredentialSourceRepository.php +++ b/src/Webauthn/Repository/UserCredentialSourceRepository.php @@ -1,8 +1,8 @@ [], 'attestationType' => 'none', 'trustPath' => [ - 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + 'type' => 'Webauthn\TrustPath\EmptyTrustPath', ], 'aaguid' => '00000000-0000-0000-0000-000000000000', 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-ZZZZZZZZZZZ'), 'userHandle' => Base64Url::encode('00000000-0000-0000-0000-000000000001'), 'counter' => 190, - 'otherUI' => null + 'otherUI' => null, ], - ] + ], ]), ], [ diff --git a/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php b/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php index 734020b5b..fa234bd63 100644 --- a/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php +++ b/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php @@ -56,7 +56,6 @@ public function setUp(): void Configure::write('Webauthn2fa.enabled', true); Configure::write('Webauthn2fa.appName', 'ACME Webauthn Server'); Configure::write('Webauthn2fa.id', 'localhost'); - } /** @@ -226,13 +225,13 @@ public function testWebauthn2faRegister() 'transports' => [], 'attestationType' => 'none', 'trustPath' => [ - 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + 'type' => 'Webauthn\TrustPath\EmptyTrustPath', ], 'aaguid' => '00000000-0000-0000-0000-000000000000', 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-YYYYYYYYYYY'), 'userHandle' => Base64Url::encode($userId), 'counter' => 191, - 'otherUI' => null + 'otherUI' => null, ]; $credential = PublicKeyCredentialSource::createFromArray($credentialData); $adapter->expects($this->once()) @@ -301,7 +300,6 @@ public function testWebauthn2faRegisterError() $this->Trait->webauthn2faRegister(); } - /** * Test webauthn2faAuthenticateOptions * @@ -370,13 +368,13 @@ public function testWebauthn2faAuthenticate() 'transports' => [], 'attestationType' => 'none', 'trustPath' => [ - 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + 'type' => 'Webauthn\TrustPath\EmptyTrustPath', ], 'aaguid' => '00000000-0000-0000-0000-000000000000', 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-YYYYYYYYYYY'), 'userHandle' => Base64Url::encode($userId), 'counter' => 191, - 'otherUI' => null + 'otherUI' => null, ]; $credential = PublicKeyCredentialSource::createFromArray($credentialData); $adapter->expects($this->once()) diff --git a/tests/TestCase/Webauthn/AuthenticateAdapterTest.php b/tests/TestCase/Webauthn/AuthenticateAdapterTest.php index ee127dc79..70c101c90 100644 --- a/tests/TestCase/Webauthn/AuthenticateAdapterTest.php +++ b/tests/TestCase/Webauthn/AuthenticateAdapterTest.php @@ -1,4 +1,5 @@ [], 'attestationType' => 'none', 'trustPath' => [ - 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + 'type' => 'Webauthn\TrustPath\EmptyTrustPath', ], 'aaguid' => '00000000-0000-0000-0000-000000000000', 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-YYYYYYYYYYY'), 'userHandle' => Base64Url::encode($userId), 'counter' => 191, - 'otherUI' => null + 'otherUI' => null, ]; $credential = PublicKeyCredentialSource::createFromArray($credentialData); $adapter->expects($this->once()) @@ -70,7 +70,6 @@ public function testGetOptions() $actual = $adapter->verifyResponse(); $this->assertEquals($credential, $actual); - $adapter = new AuthenticateAdapter($request); $this->expectException(\Assert\InvalidArgumentException::class); diff --git a/tests/TestCase/Webauthn/RegisterAdapterTest.php b/tests/TestCase/Webauthn/RegisterAdapterTest.php index b85c8ec0b..3ce86a8e8 100644 --- a/tests/TestCase/Webauthn/RegisterAdapterTest.php +++ b/tests/TestCase/Webauthn/RegisterAdapterTest.php @@ -1,4 +1,5 @@ [], 'attestationType' => 'none', 'trustPath' => [ - 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + 'type' => 'Webauthn\TrustPath\EmptyTrustPath', ], 'aaguid' => '00000000-0000-0000-0000-000000000000', 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-YYYYYYYYYYY'), 'userHandle' => Base64Url::encode($userId), 'counter' => 191, - 'otherUI' => null + 'otherUI' => null, ]; $credential = PublicKeyCredentialSource::createFromArray($credentialData); $adapter->expects($this->once()) diff --git a/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php b/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php index 81e1a84d2..77a37a367 100644 --- a/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php +++ b/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php @@ -1,4 +1,5 @@ get($userId); $userEntity = new PublicKeyCredentialUserEntity( - 'john.doe', // Username - $userId, // ID - 'John Doe' // Display name + 'john.doe', + $userId, + 'John Doe' ); $repository = new UserCredentialSourceRepository($user, $UsersTable); $credentials = $repository->findAllForUserEntity($userEntity); @@ -57,9 +58,9 @@ public function testFindAllForUserEntity() //Not found id $userEntityInvalid = new PublicKeyCredentialUserEntity( - 'john.doe', // Username - '00000000-0000-0000-0000-000000000004', // ID - 'John Doe' // Display name + 'john.doe', + '00000000-0000-0000-0000-000000000004', + 'John Doe' ); $repository = new UserCredentialSourceRepository($user, $UsersTable); $credentials = $repository->findAllForUserEntity($userEntityInvalid); @@ -81,21 +82,21 @@ public function testSaveCredentialSource() 'transports' => [], 'attestationType' => 'none', 'trustPath' => [ - 'type' => 'Webauthn\TrustPath\EmptyTrustPath' + 'type' => 'Webauthn\TrustPath\EmptyTrustPath', ], 'aaguid' => '00000000-0000-0000-0000-000000000000', 'credentialPublicKey' => Base64Url::encode('000000000000000000000000000000000000-9999999999999999999999999999999999999999-XXXXXXXXXXXXX-YYYYYYYYYYY'), 'userHandle' => Base64Url::encode($userId), 'counter' => 191, - 'otherUI' => null + 'otherUI' => null, ]; $UsersTable = TableRegistry::getTableLocator()->get('CakeDC/Users.Users'); $user = $UsersTable->get($userId); $firstKey = key($user->additional_data['webauthn_credentials']); $userEntity = new PublicKeyCredentialUserEntity( - 'john.doe', // Username - $userId, // ID - 'John Doe' // Display name + 'john.doe', + $userId, + 'John Doe' ); $publicKey = PublicKeyCredentialSource::createFromArray($credentialData); $repository = new UserCredentialSourceRepository($user, $UsersTable); From 41382588fac113235742b7214b940e28853dda8c Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Dec 2021 12:29:26 -0300 Subject: [PATCH 671/685] fixing phpstan --- phpstan-baseline.neon | 212 +++++++++++++++++++++--------------------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 146e9ed85..61ac3a319 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -3,265 +3,265 @@ parameters: - message: "#^Access to an undefined property Cake\\\\Controller\\\\Controller\\:\\:\\$Authentication\\.$#" count: 1 - path: src\Controller\Component\LoginComponent.php + path: src/Controller/Component/LoginComponent.php - message: "#^Call to an undefined method Cake\\\\Controller\\\\Controller\\:\\:getUsersTable\\(\\)\\.$#" count: 1 - path: src\Controller\Component\LoginComponent.php + path: src/Controller/Component/LoginComponent.php - - message: "#^Call to an undefined method CakeDC\\\\Users\\\\Model\\\\Table\\\\SocialAccountsTable\\:\\:validateAccount\\(\\)\\.$#" - count: 1 - path: src\Controller\SocialAccountsController.php + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:\\$Authentication\\.$#" + count: 2 + path: src/Controller/UsersController.php - - message: "#^Call to an undefined method CakeDC\\\\Users\\\\Model\\\\Table\\\\SocialAccountsTable\\:\\:resendValidation\\(\\)\\.$#" - count: 1 - path: src\Controller\SocialAccountsController.php + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:\\$OneTimePasswordAuthenticator\\.$#" + count: 3 + path: src/Controller/UsersController.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:linkSocialAccount\\(\\)\\.$#" + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$u2f_registration\\.$#" count: 1 - path: src\Controller\UsersController.php + path: src/Controller/UsersController.php - message: "#^Call to an undefined method Cake\\\\Controller\\\\Component\\:\\:handleLogin\\(\\)\\.$#" count: 3 - path: src\Controller\UsersController.php - - - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:\\$Authentication\\.$#" - count: 2 - path: src\Controller\UsersController.php + path: src/Controller/UsersController.php - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\Controller\\\\UsersController\\:\\:\\$OneTimePasswordAuthenticator\\.$#" - count: 3 - path: src\Controller\UsersController.php - - - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validationPasswordConfirm\\(\\)\\.$#" + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:changePassword\\(\\)\\.$#" count: 1 - path: src\Controller\UsersController.php + path: src/Controller/UsersController.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validationCurrentPassword\\(\\)\\.$#" + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:linkSocialAccount\\(\\)\\.$#" count: 1 - path: src\Controller\UsersController.php + path: src/Controller/UsersController.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:changePassword\\(\\)\\.$#" - count: 1 - path: src\Controller\UsersController.php + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:register\\(\\)\\.$#" + count: 2 + path: src/Controller/UsersController.php - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:resetToken\\(\\)\\.$#" count: 2 - path: src\Controller\UsersController.php + path: src/Controller/UsersController.php - - message: "#^Parameter \\#2 \\$options of method Cake\\\\Controller\\\\Component\\\\FlashComponent\\:\\:success\\(\\) expects array, string given\\.$#" + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validate\\(\\)\\.$#" + count: 2 + path: src/Controller/UsersController.php + + - + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validationCurrentPassword\\(\\)\\.$#" count: 1 - path: src\Controller\UsersController.php + path: src/Controller/UsersController.php - - message: "#^Parameter \\#2 \\$options of method Cake\\\\Controller\\\\Component\\\\FlashComponent\\:\\:error\\(\\) expects array, string given\\.$#" + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validationPasswordConfirm\\(\\)\\.$#" count: 1 - path: src\Controller\UsersController.php + path: src/Controller/UsersController.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:register\\(\\)\\.$#" - count: 2 - path: src\Controller\UsersController.php + message: "#^Parameter \\#1 \\$message of method Cake\\\\Controller\\\\Controller\\:\\:log\\(\\) expects string, Exception given\\.$#" + count: 1 + path: src/Controller/UsersController.php - message: "#^Parameter \\#1 \\$object of method Cake\\\\Controller\\\\Controller\\:\\:paginate\\(\\) expects Cake\\\\ORM\\\\Query\\|Cake\\\\ORM\\\\Table\\|string\\|null, Cake\\\\Datasource\\\\RepositoryInterface given\\.$#" count: 1 - path: src\Controller\UsersController.php + path: src/Controller/UsersController.php - - message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$u2f_registration\\.$#" + message: "#^Parameter \\#2 \\$options of method Cake\\\\Controller\\\\Component\\\\FlashComponent\\:\\:error\\(\\) expects array, string given\\.$#" count: 1 - path: src\Controller\UsersController.php + path: src/Controller/UsersController.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validate\\(\\)\\.$#" - count: 2 - path: src\Controller\UsersController.php + message: "#^Parameter \\#2 \\$options of method Cake\\\\Controller\\\\Component\\\\FlashComponent\\:\\:success\\(\\) expects array, string given\\.$#" + count: 1 + path: src/Controller/UsersController.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:socialLogin\\(\\)\\.$#" + message: "#^Parameter \\#2 \\$usersTable of class CakeDC\\\\Users\\\\Webauthn\\\\RegisterAdapter constructor expects CakeDC\\\\Users\\\\Model\\\\Table\\\\UsersTable\\|null, Cake\\\\ORM\\\\Table given\\.$#" count: 1 - path: src\Identifier\SocialIdentifier.php + path: src/Controller/UsersController.php - - message: "#^Parameter \\#2 \\$request of method CakeDC\\\\Users\\\\Utility\\\\UsersUrl\\:\\:checkActionOnRequest\\(\\) expects Cake\\\\Http\\\\ServerRequest, Psr\\\\Http\\\\Message\\\\ServerRequestInterface given\\.$#" + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:socialLogin\\(\\)\\.$#" count: 1 - path: src\Middleware\SocialAuthMiddleware.php + path: src/Identifier/SocialIdentifier.php - message: "#^Parameter \\#1 \\$request of method CakeDC\\\\Users\\\\Middleware\\\\SocialAuthMiddleware\\:\\:goNext\\(\\) expects Cake\\\\Http\\\\ServerRequest, Psr\\\\Http\\\\Message\\\\ServerRequestInterface given\\.$#" count: 1 - path: src\Middleware\SocialAuthMiddleware.php + path: src/Middleware/SocialAuthMiddleware.php - message: "#^Parameter \\#2 \\$request of method CakeDC\\\\Users\\\\Utility\\\\UsersUrl\\:\\:checkActionOnRequest\\(\\) expects Cake\\\\Http\\\\ServerRequest, Psr\\\\Http\\\\Message\\\\ServerRequestInterface given\\.$#" count: 1 - path: src\Middleware\SocialEmailMiddleware.php + path: src/Middleware/SocialAuthMiddleware.php - message: "#^Parameter \\#1 \\$request of method CakeDC\\\\Users\\\\Middleware\\\\SocialAuthMiddleware\\:\\:goNext\\(\\) expects Cake\\\\Http\\\\ServerRequest, Psr\\\\Http\\\\Message\\\\ServerRequestInterface given\\.$#" count: 1 - path: src\Middleware\SocialEmailMiddleware.php + path: src/Middleware/SocialEmailMiddleware.php - - message: "#^Call to an undefined method Cake\\\\Datasource\\\\EntityInterface\\:\\:updateToken\\(\\)\\.$#" + message: "#^Parameter \\#2 \\$request of method CakeDC\\\\Users\\\\Utility\\\\UsersUrl\\:\\:checkActionOnRequest\\(\\) expects Cake\\\\Http\\\\ServerRequest, Psr\\\\Http\\\\Message\\\\ServerRequestInterface given\\.$#" count: 1 - path: src\Model\Behavior\BaseTokenBehavior.php - - - - message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$SocialAccounts\\.$#" - count: 5 - path: src\Model\Behavior\LinkSocialBehavior.php + path: src/Middleware/SocialEmailMiddleware.php - - message: "#^Negated boolean expression is always false\\.$#" + message: "#^Call to an undefined method Cake\\\\Datasource\\\\EntityInterface\\:\\:updateToken\\(\\)\\.$#" count: 1 - path: src\Model\Behavior\LinkSocialBehavior.php + path: src/Model/Behavior/BaseTokenBehavior.php - message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$social_accounts\\.$#" count: 2 - path: src\Model\Behavior\LinkSocialBehavior.php + path: src/Model/Behavior/LinkSocialBehavior.php - - message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\PasswordBehavior\\:\\:resetToken\\(\\) should return string but returns Cake\\\\Datasource\\\\EntityInterface\\|false\\.$#" - count: 1 - path: src\Model\Behavior\PasswordBehavior.php + message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$SocialAccounts\\.$#" + count: 5 + path: src/Model/Behavior/LinkSocialBehavior.php - - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:findByUsernameOrEmail\\(\\)\\.$#" + message: "#^Negated boolean expression is always false\\.$#" count: 1 - path: src\Model\Behavior\PasswordBehavior.php + path: src/Model/Behavior/LinkSocialBehavior.php - message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$password\\.$#" count: 1 - path: src\Model\Behavior\PasswordBehavior.php + path: src/Model/Behavior/PasswordBehavior.php - - message: "#^Call to an undefined method Cake\\\\Datasource\\\\EntityInterface\\:\\:checkPassword\\(\\)\\.$#" + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$password_confirm\\.$#" count: 1 - path: src\Model\Behavior\PasswordBehavior.php + path: src/Model/Behavior/PasswordBehavior.php - - message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$password_confirm\\.$#" + message: "#^Call to an undefined method Cake\\\\Datasource\\\\EntityInterface\\:\\:checkPassword\\(\\)\\.$#" count: 1 - path: src\Model\Behavior\PasswordBehavior.php + path: src/Model/Behavior/PasswordBehavior.php - - message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$validated\\.$#" + message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:findByUsernameOrEmail\\(\\)\\.$#" count: 1 - path: src\Model\Behavior\RegisterBehavior.php + path: src/Model/Behavior/PasswordBehavior.php - - message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$isValidateEmail\\.$#" + message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\PasswordBehavior\\:\\:resetToken\\(\\) should return string but returns Cake\\\\Datasource\\\\EntityInterface\\|false\\.$#" count: 1 - path: src\Model\Behavior\RegisterBehavior.php + path: src/Model/Behavior/PasswordBehavior.php - - message: "#^Cannot call method tokenExpired\\(\\) on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$activation_date\\.$#" count: 1 - path: src\Model\Behavior\RegisterBehavior.php + path: src/Model/Behavior/RegisterBehavior.php - message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$active\\.$#" count: 1 - path: src\Model\Behavior\RegisterBehavior.php + path: src/Model/Behavior/RegisterBehavior.php - - message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$activation_date\\.$#" + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$token_expires\\.$#" count: 1 - path: src\Model\Behavior\RegisterBehavior.php + path: src/Model/Behavior/RegisterBehavior.php - - message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$token_expires\\.$#" + message: "#^Access to an undefined property Cake\\\\Datasource\\\\EntityInterface\\:\\:\\$validated\\.$#" + count: 1 + path: src/Model/Behavior/RegisterBehavior.php + + - + message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$isValidateEmail\\.$#" count: 1 - path: src\Model\Behavior\RegisterBehavior.php + path: src/Model/Behavior/RegisterBehavior.php - message: "#^Call to an undefined method Cake\\\\ORM\\\\Table\\:\\:validationRegister\\(\\)\\.$#" count: 1 - path: src\Model\Behavior\RegisterBehavior.php + path: src/Model/Behavior/RegisterBehavior.php - - message: "#^Cannot access property \\$token on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" + message: "#^Cannot call method tokenExpired\\(\\) on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" + count: 1 + path: src/Model/Behavior/RegisterBehavior.php + + - + message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\SocialAccount\\:\\:\\$active\\.$#" count: 1 - path: src\Model\Behavior\SocialAccountBehavior.php + path: src/Model/Behavior/SocialAccountBehavior.php - message: "#^Cannot access property \\$active on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" count: 2 - path: src\Model\Behavior\SocialAccountBehavior.php + path: src/Model/Behavior/SocialAccountBehavior.php - - message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:validateAccount\\(\\) should return CakeDC\\\\Users\\\\Model\\\\Entity\\\\User but returns Cake\\\\Datasource\\\\EntityInterface\\.$#" + message: "#^Cannot access property \\$token on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" count: 1 - path: src\Model\Behavior\SocialAccountBehavior.php + path: src/Model/Behavior/SocialAccountBehavior.php - - message: "#^Parameter \\#1 \\$socialAccount of method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:_activateAccount\\(\\) expects CakeDC\\\\Users\\\\Model\\\\Entity\\\\SocialAccount, array\\|Cake\\\\Datasource\\\\EntityInterface given\\.$#" + message: "#^Cannot access property \\$user on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" count: 1 - path: src\Model\Behavior\SocialAccountBehavior.php + path: src/Model/Behavior/SocialAccountBehavior.php - - message: "#^Cannot access property \\$user on array\\|Cake\\\\Datasource\\\\EntityInterface\\.$#" + message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:resendValidation\\(\\) should return CakeDC\\\\Users\\\\Model\\\\Entity\\\\User but returns array\\.$#" count: 1 - path: src\Model\Behavior\SocialAccountBehavior.php + path: src/Model/Behavior/SocialAccountBehavior.php - - message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:resendValidation\\(\\) should return CakeDC\\\\Users\\\\Model\\\\Entity\\\\User but returns array\\.$#" + message: "#^Method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:validateAccount\\(\\) should return CakeDC\\\\Users\\\\Model\\\\Entity\\\\User but returns Cake\\\\Datasource\\\\EntityInterface\\.$#" count: 1 - path: src\Model\Behavior\SocialAccountBehavior.php + path: src/Model/Behavior/SocialAccountBehavior.php - - message: "#^Access to an undefined property CakeDC\\\\Users\\\\Model\\\\Entity\\\\SocialAccount\\:\\:\\$active\\.$#" + message: "#^Parameter \\#1 \\$socialAccount of method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\SocialAccountBehavior\\:\\:_activateAccount\\(\\) expects CakeDC\\\\Users\\\\Model\\\\Entity\\\\SocialAccount, array\\|Cake\\\\Datasource\\\\EntityInterface given\\.$#" count: 1 - path: src\Model\Behavior\SocialAccountBehavior.php + path: src/Model/Behavior/SocialAccountBehavior.php - message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$SocialAccounts\\.$#" count: 4 - path: src\Model\Behavior\SocialBehavior.php + path: src/Model/Behavior/SocialBehavior.php - message: "#^Access to an undefined property Cake\\\\ORM\\\\Table\\:\\:\\$isValidateEmail\\.$#" count: 1 - path: src\Model\Behavior\SocialBehavior.php + path: src/Model/Behavior/SocialBehavior.php - message: "#^Parameter \\#3 \\$tokenExpiration of method CakeDC\\\\Users\\\\Model\\\\Behavior\\\\BaseTokenBehavior\\:\\:_updateActive\\(\\) expects int, string given\\.$#" count: 1 - path: src\Model\Behavior\SocialBehavior.php + path: src/Model/Behavior/SocialBehavior.php - message: "#^Method CakeDC\\\\Users\\\\Model\\\\Entity\\\\User\\:\\:_setTos\\(\\) should return bool but returns string\\.$#" count: 1 - path: src\Model\Entity\User.php - - - - message: "#^Property CakeDC\\\\Users\\\\Shell\\\\UsersShell\\:\\:\\$Users \\(CakeDC\\\\Users\\\\Model\\\\Table\\\\UsersTable\\) does not accept Cake\\\\Datasource\\\\RepositoryInterface\\.$#" - count: 1 - path: src\Shell\UsersShell.php + path: src/Model/Entity/User.php - message: "#^Cannot access property \\$username on bool\\.$#" count: 2 - path: src\Shell\UsersShell.php + path: src/Shell/UsersShell.php + + - + message: "#^Property CakeDC\\\\Users\\\\Shell\\\\UsersShell\\:\\:\\$Users \\(CakeDC\\\\Users\\\\Model\\\\Table\\\\UsersTable\\) does not accept Cake\\\\Datasource\\\\RepositoryInterface\\.$#" + count: 1 + path: src/Shell/UsersShell.php - - message: "#^Parameter \\#1 \\$message of method Cake\\\\Controller\\\\Controller\\:\\:log\\(\\)\\ expects string, Exception given.$#" + message: "#^Parameter \\#2 \\$usersTable of class CakeDC\\\\Users\\\\Webauthn\\\\Repository\\\\UserCredentialSourceRepository constructor expects CakeDC\\\\Users\\\\Model\\\\Table\\\\UsersTable\\|null, Cake\\\\ORM\\\\Table given\\.$#" count: 1 - path: src\Controller\Traits\OneTimePasswordVerifyTrait.php + path: src/Webauthn/BaseAdapter.php From bebd6d443084c6f1c5a0a264b4dc1127a581e1ad Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Mon, 20 Dec 2021 12:40:04 -0300 Subject: [PATCH 672/685] Check if user already have setup webauthn2fa --- src/Controller/Traits/Webauthn2faTrait.php | 19 ++++++- .../Traits/Webauthn2faTraitTest.php | 57 +++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/Controller/Traits/Webauthn2faTrait.php b/src/Controller/Traits/Webauthn2faTrait.php index 95c6ad620..301c08acc 100644 --- a/src/Controller/Traits/Webauthn2faTrait.php +++ b/src/Controller/Traits/Webauthn2faTrait.php @@ -14,6 +14,7 @@ namespace CakeDC\Users\Controller\Traits; use Cake\Core\Configure; +use Cake\Http\Exception\BadRequestException; use Cake\Log\Log; use Cake\Routing\Router; use CakeDC\Auth\Authenticator\TwoFactorAuthenticator; @@ -43,8 +44,14 @@ public function webauthn2fa() public function webauthn2faRegisterOptions() { $adapter = $this->getWebauthn2faRegisterAdapter(); + if (!$adapter->hasCredential()) { + return $this->getResponse() + ->withStringBody(json_encode($adapter->getOptions())); + } - return $this->getResponse()->withStringBody(json_encode($adapter->getOptions())); + throw new BadRequestException( + __d('cake_d_c/users', 'User already has configured webauthn2fa') + ); } /** @@ -56,9 +63,15 @@ public function webauthn2faRegisterOptions() public function webauthn2faRegister(): \Cake\Http\Response { try { - $this->getWebauthn2faRegisterAdapter()->verifyResponse(); + $adapter = $this->getWebauthn2faRegisterAdapter(); + if (!$adapter->hasCredential()) { + $adapter->verifyResponse(); - return $this->getResponse()->withStringBody(json_encode(['success' => true])); + return $this->getResponse()->withStringBody(json_encode(['success' => true])); + } + throw new BadRequestException( + __d('cake_d_c/users', 'User already has configured webauthn2fa') + ); } catch (\Throwable $e) { $user = $this->request->getSession()->read('Webauthn2fa.User'); Log::debug(__('Register error with webauthn for user id: {0}', $user['id'] ?? 'empty')); diff --git a/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php b/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php index fa234bd63..b247289c8 100644 --- a/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php +++ b/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php @@ -15,6 +15,7 @@ use Base64Url\Base64Url; use Cake\Core\Configure; +use Cake\Http\Exception\BadRequestException; use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; use Cake\ORM\TableRegistry; @@ -164,6 +165,34 @@ public function testWebauthn2faDontRequireRegister() ); } + /** + * Test webauthn2faRegisterOptions method when DON'T require register + * + * @return void + */ + public function testWebauthn2faRegisterOptionsDontRequireRegister() + { + $request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->setMethods(['getSession', 'is']) + ->getMock(); + $this->Trait->setRequest($request); + $request->expects($this->any()) + ->method('is') + ->with( + $this->equalTo('ssl') + )->will($this->returnValue(true)); + + $table = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users'); + $user = $table->get('00000000-0000-0000-0000-000000000001'); + $this->_mockSession([ + 'Webauthn2fa.User' => $user, + ]); + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('User already has configured webauthn2fa'); + $this->Trait->webauthn2faRegisterOptions(); + } + /** * Test webauthn2faRegisterOptions method * @@ -199,6 +228,34 @@ public function testWebauthn2faRegisterOptions() ); } + /** + * Test webauthn2faRegister method when DON'T require register + * + * @return void + */ + public function testWebauthn2faRegisterDontRequireRegister() + { + $request = $this->getMockBuilder('Cake\Http\ServerRequest') + ->setMethods(['getSession', 'is']) + ->getMock(); + $this->Trait->setRequest($request); + $request->expects($this->any()) + ->method('is') + ->with( + $this->equalTo('ssl') + )->will($this->returnValue(true)); + + $table = TableRegistry::getTableLocator() + ->get('CakeDC/Users.Users'); + $user = $table->get('00000000-0000-0000-0000-000000000001'); + $this->_mockSession([ + 'Webauthn2fa.User' => $user, + ]); + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('User already has configured webauthn2fa'); + $this->Trait->webauthn2faRegister(); + } + /** * Test webauthn2faRegisterOptions method * From 1ba39937a74969a38afbf6d6c20c3c369b4294c7 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 21 Dec 2021 07:17:37 -0300 Subject: [PATCH 673/685] improved translation message lookup --- templates/Users/webauthn2fa.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/templates/Users/webauthn2fa.php b/templates/Users/webauthn2fa.php index dab4aba4a..23977e0ca 100644 --- a/templates/Users/webauthn2fa.php +++ b/templates/Users/webauthn2fa.php @@ -15,16 +15,16 @@ Flash->render() ?>

Html->link( __('Reload'), From 318a45811ed3616561033e99e48be0289e27df9f Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 21 Dec 2021 07:19:20 -0300 Subject: [PATCH 674/685] Updated phpdoc --- templates/Users/webauthn2fa.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/Users/webauthn2fa.php b/templates/Users/webauthn2fa.php index 23977e0ca..ae1686af0 100644 --- a/templates/Users/webauthn2fa.php +++ b/templates/Users/webauthn2fa.php @@ -1,7 +1,8 @@ Html->script('CakeDC/Users.webauthn.js', ['block' => true]); $this->assign('title', __('Two-factor authentication')); From d6b45a1e0e58e2c6ed5028190f10d1bf56b9ac82 Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Tue, 21 Dec 2021 08:09:29 -0300 Subject: [PATCH 675/685] Prepare release for 9.3.0 --- .semver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.semver b/.semver index a0290e8f4..40fab0e1b 100644 --- a/.semver +++ b/.semver @@ -1,5 +1,5 @@ --- :major: 9 -:minor: 2 +:minor: 3 :patch: 0 :special: '' From d69543be6726d25a7e37b0c19f054ba680b4c6f9 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Sat, 22 Jan 2022 14:03:43 -0400 Subject: [PATCH 676/685] fix some tests --- .../Traits/Integration/LoginTraitIntegrationTest.php | 12 ++++++------ .../Integration/RegisterTraitIntegrationTest.php | 4 ++-- .../Integration/SimpleCrudTraitIntegrationTest.php | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index 982806ea1..efd2dc80b 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -76,8 +76,8 @@ public function testLoginGetRequestNoSocialLogin() $this->assertResponseNotContains('Username or password is incorrect'); $this->assertResponseContains(''); $this->assertResponseContains('Please enter your username and password'); - $this->assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains('input type="password" name="password" required="required" id="password" aria-required="true"/>'); $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains('Register'); @@ -102,8 +102,8 @@ public function testLoginGetRequest() $this->assertResponseNotContains('Username or password is incorrect'); $this->assertResponseContains(''); $this->assertResponseContains('Please enter your username and password'); - $this->assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains('input type="password" name="password" required="required" id="password" aria-required="true"/>'); $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains('Register'); @@ -131,8 +131,8 @@ public function testLoginPostRequestInvalidPassword() $this->assertResponseContains('Username or password is incorrect'); $this->assertResponseContains(''); $this->assertResponseContains('Please enter your username and password'); - $this->assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); + $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains(''); } diff --git a/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php index 0866a5c84..8c7d4e852 100644 --- a/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/RegisterTraitIntegrationTest.php @@ -48,7 +48,7 @@ public function testRegister() $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); $this->assertResponseContains(''); } @@ -83,7 +83,7 @@ public function testRegisterPostWithErrors() $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains(''); - $this->assertResponseContains(''); + $this->assertResponseContains(''); $this->assertResponseContains(''); } diff --git a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php index 90df2fcc2..9b606146e 100644 --- a/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/SimpleCrudTraitIntegrationTest.php @@ -95,9 +95,9 @@ public function testCrud() $this->get('/users/edit/00000000-0000-0000-0000-000000000006'); $this->assertResponseContains('assertResponseContains('id="username" aria-required="true" value="user-6"'); $this->assertResponseContains('assertResponseContains('id="email" aria-required="true" value="6@example.com"'); $this->assertResponseContains('Active'); From 8d888d92706efc9e5b793fd6d98b454da7c60998 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Sat, 22 Jan 2022 14:05:25 -0400 Subject: [PATCH 677/685] add CI tests for php 8.1 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb98b5723..032c79a25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - php-version: ['7.3', '7.4', '8.0'] + php-version: ['7.3', '7.4', '8.0', '8.1'] db-type: [sqlite, mysql, pgsql] prefer-lowest: [''] From df6dfb4b0ccf5e22666f33e95227929ff12e73c9 Mon Sep 17 00:00:00 2001 From: Alberto Rodriguez Date: Mon, 24 Jan 2022 13:32:02 -0400 Subject: [PATCH 678/685] minor fix --- .../Traits/Integration/LoginTraitIntegrationTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php index efd2dc80b..1ae48b8bb 100644 --- a/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php +++ b/tests/TestCase/Controller/Traits/Integration/LoginTraitIntegrationTest.php @@ -77,7 +77,7 @@ public function testLoginGetRequestNoSocialLogin() $this->assertResponseContains(''); $this->assertResponseContains('Please enter your username and password'); $this->assertResponseContains(''); - $this->assertResponseContains('input type="password" name="password" required="required" id="password" aria-required="true"/>'); + $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains('Register'); @@ -103,7 +103,7 @@ public function testLoginGetRequest() $this->assertResponseContains(''); $this->assertResponseContains('Please enter your username and password'); $this->assertResponseContains(''); - $this->assertResponseContains('input type="password" name="password" required="required" id="password" aria-required="true"/>'); + $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains(''); $this->assertResponseContains('Register'); From c1bb3b40e69a23be1415ac6829b25dd5f8ec71f1 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Mon, 24 Jan 2022 22:44:22 +0300 Subject: [PATCH 679/685] prepare to release --- CHANGELOG.md | 7 +++++ composer.json | 1 + tests/Fixture/UsersFixture.php | 4 +-- .../Traits/Webauthn2faTraitTest.php | 28 ++++--------------- .../UserCredentialSourceRepositoryTest.php | 2 ++ 5 files changed, 18 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8eea9d31..78c464692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ Changelog ========= +Releases for CakePHP 4.3 + +* 11.0.0 + * Switched tests to new cakephp schema + * Update to PHPUnit 9.5 + + Releases for CakePHP 4 ------------- * 9.2.0 diff --git a/composer.json b/composer.json index f03271f39..3a94372d7 100644 --- a/composer.json +++ b/composer.json @@ -27,6 +27,7 @@ "source": "https://github.com/CakeDC/users" }, "minimum-stability": "dev", + "prefer-stable": true, "require": { "php": ">=7.2.0", "cakephp/cakephp": "^4.0", diff --git a/tests/Fixture/UsersFixture.php b/tests/Fixture/UsersFixture.php index 485714e1e..d48f6dc55 100644 --- a/tests/Fixture/UsersFixture.php +++ b/tests/Fixture/UsersFixture.php @@ -47,7 +47,7 @@ public function init(): void 'role' => 'admin', 'created' => '2015-06-24 17:33:54', 'modified' => '2015-06-24 17:33:54', - 'additional_data' => json_encode([ + 'additional_data' => [ 'u2f_registration' => [ 'keyHandle' => 'fake key handle', 'publicKey' => 'afdoaj0-23u423-ad ujsf-as8-0-afsd', @@ -70,7 +70,7 @@ public function init(): void 'otherUI' => null, ], ], - ]), + ], 'last_login' => '2015-06-24 17:33:54', ], [ diff --git a/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php b/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php index b247289c8..e47f2c661 100644 --- a/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php +++ b/tests/TestCase/Controller/Traits/Webauthn2faTraitTest.php @@ -104,18 +104,10 @@ public function testWebauthn2faIsRegister() $this->_mockSession([ 'Webauthn2fa.User' => $user, ]); - $this->Trait->expects($this->at(1)) - ->method('set') - ->with( - $this->equalTo('isRegister'), - $this->equalTo(true) - ); - $this->Trait->expects($this->at(2)) + $this->Trait + ->expects($this->exactly(2)) ->method('set') - ->with( - $this->equalTo('username'), - $this->equalTo('user-2') - ); + ->withConsecutive(['isRegister', true], ['username', 'user-2']); $this->Trait->webauthn2fa(); $this->assertSame( $user, @@ -146,18 +138,10 @@ public function testWebauthn2faDontRequireRegister() $this->_mockSession([ 'Webauthn2fa.User' => $user, ]); - $this->Trait->expects($this->at(1)) - ->method('set') - ->with( - $this->equalTo('isRegister'), - $this->equalTo(false) - ); - $this->Trait->expects($this->at(2)) + $this->Trait + ->expects($this->exactly(2)) ->method('set') - ->with( - $this->equalTo('username'), - $this->equalTo('user-1') - ); + ->withConsecutive(['isRegister', false], ['username', 'user-1']); $this->Trait->webauthn2fa(); $this->assertSame( $user, diff --git a/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php b/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php index 77a37a367..021d08c8b 100644 --- a/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php +++ b/tests/TestCase/Webauthn/Repository/UserCredentialSourceRepositoryTest.php @@ -74,6 +74,8 @@ public function testFindAllForUserEntity() */ public function testSaveCredentialSource() { + \Cake\Database\TypeFactory::map('json', \Cake\Database\Type\JsonType::class); + $publicKeyCredentialId = '12b37486-9299-4331-ac33-85b2d985b6fe'; $userId = '00000000-0000-0000-0000-000000000001'; $credentialData = [ From 012326d2af070efa80e9c080151acf8831984abd Mon Sep 17 00:00:00 2001 From: Evgeny Tomenko Date: Thu, 27 Jan 2022 15:18:44 +0300 Subject: [PATCH 680/685] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f87f94f60..fbd5af5f4 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Versions and branches | CakePHP | CakeDC Users Plugin | Tag | Notes | | :-------------: | :------------------------: | :--: | :---- | -| ^4.0 | [master](https://github.com/cakedc/users/tree/master) | 9.0.5 | stable | +| ^4.3 | [master](https://github.com/cakedc/users/tree/master) | 11.0.0 | stable | | ^4.3 | [11.0](https://github.com/cakedc/users/tree/11.next-cake4) | 11.0.0 | stable | | ^4.0 | [9.0](https://github.com/cakedc/users/tree/9.next) | 9.0.5 | stable | | ^3.7 <4.0 | [8.5](https://github.com/cakedc/users/tree/8.next) | 8.5.1 | stable | From 3ce830963d44f66d035d4063721b57cf8763e794 Mon Sep 17 00:00:00 2001 From: Kevin Pfeifer Date: Fri, 11 Mar 2022 13:32:37 +0100 Subject: [PATCH 681/685] added german translation --- resources/locales/de_DE/users.mo | Bin 0 -> 15667 bytes resources/locales/de_DE/users.po | 817 +++++++++++++++++++++++++++++++ 2 files changed, 817 insertions(+) create mode 100644 resources/locales/de_DE/users.mo create mode 100644 resources/locales/de_DE/users.po diff --git a/resources/locales/de_DE/users.mo b/resources/locales/de_DE/users.mo new file mode 100644 index 0000000000000000000000000000000000000000..61a8ac7065103115bcd5a87e1a3a01659e891cac GIT binary patch literal 15667 zcmcJV3y@@0dB?8=1QrxTd;n_huE;}~*&R^S*QG z6nr}TJUk2jC43Hi1a5&(KHWa=fG6_&a;S21@N9S^{8e}dq)PBv$FIOA^89Uh68tV4 zhW`Se49|Xw?f*h}9?zG+7s8`Z_1*#1-ffN_gy-^nKctD^+m8PV&*1rIQ0<@2!!zLy zI0BEr7sI!}P4G{k=JAhE?K}+6fsaDixBKF3eG{0HF%^8W@t4SwG}Kk9fgjcL4RLXBfLJPz)I8t)X0;1MXfd};hu~(Y#x;&DP~*MA@gUSZu7jFi1T~%osQKIg)$i+|8w55niehoQ#zOcsrw!A7X(Q7F0W zf~tQ2hOhypuWyDgfVV@*dBwf|52*If#2936+o0OL21?!;FXh=@ymY{dT7_{9C$I$7eKB5wT^Fv z3?cX|L^Q#-;5hsdJOa1T*?xE{RD1sbHJ*QlWANYMiSUIO4@(tngR+k!@Zu)~!Rz4x zowOQDU;8YS9(@s>0KWw#-@k*> zyPrCS7g~KDhmy-t$dUvZR6Do0_jg0B)2AIj2Q|J2;mPm>oXc_WG^lcCz!aVhHNKmn z?B)(gmEb=3BKU2naXkg+auOVJyc8bK^A30l9EY0!6jZsIV++27=N{C$eavwM%3l5& zN)F$HvZJ3sjrSCcRO|ONsP-CA>(GIhz~6%mE%-V_RKb5k*~<<-;dSs9I17IO zFNZV3c3!ta$?+=?Qwko2FNRN|6SX%1S^6M_EOl@z+zmemUkHy!$yENOP~&?Q#B~JA z@KpG2D0zGUYCZoLs@;d6^x%XM_5}DWsCMg6`uI_(e*YY9gFl9{qZeV^(vyRbCW0ey z1H2ikzgr+C6ub{I)!>WpH26cPevU_In&)1q@wTA!sRt$Rx4~23?T{r1-Vf*DpFu<$ zY-Q52(f_FiU_lIyNd=zS4V=RWo9YK~TcpH2={2bIee;sPv{{=OVjVPtY zI|`*QuY_8^&qKBM5R@JK6v}^|_fq>j0VVG?+yq|(HSW8i=JQpT{~h=IgwY__PX1Hj ziST7m>v9bohY7qKehl(2c!V#F_xU(C+1*}v8EnE=!4E;L%ULLg*6~e_Z--jv+oAgT zTPS&d4{AM5VGvJ%&migZNs`{bLl1mrN$)4M^}y$C7DmSKjmg5enwbe&!lbByY z@Q3go(g#Vh5q+LY`Y7oWq?n}7lSvDt2|e(6t3~A-u^Ih3;BwzodW%VzHF+A8F6gtL zr1jBfii8>mzfD>q9U=8d(yLoYzezew!sVFHrF_4V^dZt~NyVqZkJH@49njc2yvyYY z?;_n@dY0|%b2tG)*c# zXYk|Iq^n7(%Y3inGvPI)4oN=$jihTyBP4zPNMGCXPLzhVR+Q)4H#J&Ion}&Nr=kBf z)M__|l5|rTWl1#DOzQPG-M*=t_2NyJZQHEMmxYJpESXyh#-=92ZhJmXgRxpI?sUVM z1Jfam)st@0PV*hgZuin|7`3uEsxO7dqE=Fmx^dmV;eD$frtNMx8?W(NFXm{X&UY4e zn{n7kj>W0%HH^rQ7owy!?A!A_gn5rK<@sE%)ncSIGa|!d41lU(-id3;Tv7{rd7Sm% zEVX-C7`cHr<18L{mA7k2)C!SOl7{8?OgS8h53mwn8u5Yu@h%e zeSwxV2s_C*??Ihuh6?ztjjFwj1kHrXCciUk-ZpF;;x#6p~ zyp}~+uUHo6vC6Z6re`yRP1M;$C8QK(!LDYMHsWv!Wm#-z_2RiR@T`T&+O60$vr4qP z+UZ=9Erk7A?KF*R-EcAKHZ{h863U3{<*Y(6=u0BkqS;lsDD1T2D38N#wiHHytX9 zR97XexR57yS<06|b}A*YOG!J87GhUd#jECL+8i}Yy*r6pb@MZv$g+0E&ym*#yOS*M zhWpiq{b`!p({49Vs<9sW#nRQHuAG3;*TpEWbP*b54z5T{CzJJH(smL|&KbASO49i- z$&II}wUK_U+gb|iN#1EiOL5(=Rju7wG8N|9tyX(ch8WfBG@geTsnMLpcs88P+KVz+ zDeq)zoKB&g{yB?xMV)S~8TlMLbiCGP=26wBfih00MVo&0ynFNIU5=bhcc~Kxd!s^- z=9iJ32==2#5$oE{lI4>4tyjfcQ`=}P_r?fu;`?+e-w?lCavj5IReG=sV_;k){JX5CpI>u ztTuX^_G0VTI?iocWyOwgFF6yi&DrWk#r}8oe=*f%bl&HfPAeOm)~FcQFV=3UW}HT| z*zcNVY}R$*m9KSaeUgXIcquIxx?A+b)Z00ZL-rn2@icCIWq7|#)mq_sG#MX3vzQi2;^ zG%#mVVj*6bMUHsUgL3Be@URWI7JD4fsg=crM%FG&Z zN*qgMvqo5?_RSC~HS*{fdx(GMc4j9;pRH+0)y)xLxL+I}6Y8A}bn8{M^0kXnYQdFU zXM8GI8J;U{dR+CgKX$$H8^>TB|Dq_*B-uGR?(idvU)4)8iNJ*N<~y9Yp+jD7^ZcG4 zn_O42I!p@3U02)`i?mah97Md(=`NKE_|`SLLeE?ec9~32p0=&2yQ+RFro)Q3y+jAM zFP5vF+XK-dyAPnlc7HeOVEW0tQ$v)&A#J3CM&O-C^>t;r)+yt&DjH)EQqEoNdR)z^k)!b^Hjo|;XNq%Oa5#w-P6SZsHDTh$%h>Dp_m z+CQJx%T21PB2@*|y!K^_tx$r{k;K0AQm(pP8x{~k5-asj&)(qt>DM+=Jx>_7BsDQH zZQl@<;;wI?WU)y)+rGi9Uy|nB^|a~U&j zaG6oxh~}6RzL~tTtU?X@I>YnvQXu8l=@FWdTJPkgX#`xn8xW6^h+hZ7tm`=w4o%jF z(AJ#%(QxYEfh#9=&4h<14o*)V*uP=wz|cX)u9rjOSmkJV@s^7(9@=ur(8x$Qa>?i= zBQMx8vSrH#9lVBSvM9}45hvEskesy9iyHCJOdKtYhI_~M?>RKKXCmA-v2Sd0@8x6T z;|C|Er!Vv6M%k}6?3>&-(I3pn@Rki+lXMADhh{kFjfP#MxtZf@l5SN5ld%ANjoZVK z3%71KGPK9;?V86_JJ#L8CBs{WM>hPQTqN$~vTNm@ZbATIZWHZpIJRde-fVuEE5$@H z?~dRqX5L0mq|aHLbahs9HM_w$x@il{bC1M5QJU16Dp`~W7vqe}pI{;nU5WXaaL(45 zTX`Tu+$r%@BW}dAOg9bfevDt@RifL%;#D|dj&_ZBj!Q`j+Lnh)V_59bR~TnpAT$_i ztyvmKFg7nAsLArkB(@+{6do?otiA(*e znpQfWY-Y{^thu=B(PY_}+;F(_vAXW}>^jD2YRafyxZGO^s|OrilQ&SJxYgp)*Vy9Y zwZC#FhTdU0u`|xW82((`Y|%)q*}{>gk0Y7@iP`QVV;4QTF0C4usos(X*LSbe$iCSW zIvTiFgEe->Q8tTHV!gdW&i3<+$8cApWe;|&opA`0mRO%sab8+-4)7es3*Tk@&d*cE zF6UtD#+MbtGx4A8b+x0#iTjhL(2U#VZ( zSc=7{Y-=ViVFKMst;4#;As1W7x#bP^N42I|L;pjf;aZn7{c_L5$-ecdH`mhr5PMF# zz$)s;tovcs5~*bPvy7vFF5$j=wW^9D3B7 zi_^lZ*y$M+(7uCAxD zb_?@X3^UMtIfU@#{RFJ2tdriI$t9ZUmWN}anyEHxPw2-YN;Os^_QhEJ}{- zeAsa#W}nH)$hpkYZiAC*p*>QBtJn^gZP4K2ATF80u~el|O$seiL$$QC`RP=*<@uHS z`C}ih((Er4b6w9+*{W!}Y^ZE8nyE818yhh@@6=Ok1HVicY~*f?rB*dJr%dX9Enhe6 zYMD@SwJ=zV)g{c{Z9|TA-}lwb9NLYeG4-q;|2gY%54_d@aD^O~%ciMvt7amP8BPrC z(_aV+N4kDFvtyNtg{+!78dQvB{EZ^EHM^@$o4=Fe4SWOrzDr@4k-7S@q4aFbR%r5! zD~JjwIC!zXti5E;d74&?C(PBny+MY2RITp;)(NHq$^(2kZ1V;6nX<4y&)*Guh&_RF^8_QhaYt5r4e z)vj~hQV12xDO@JSv?~`YI#ivDQ#Buk59nTBUe}x5s46vMPr*1AYb~qfqbZ2hWDD1>}KWmO4!|eYiw&ZN-|2|;0Y>o?@3cI5L2XNioa;D@0j$;`QgcsVQ zwBak3_A3_hzf~3%y3TIQ_9C;9%9amnkE5m)L9vnWA1H`{e$KOk`YQCPIN;lWff%l% zBY3|pGcaFRiFL$T|pOtVUwkHLGg~0*??YVNl!2Hz9V>V*?T%**Q z0$6X%<$Pb!s%0MP2%vjWl%SUzRp}q+0<+fkI~<#B5t7+E39ADYW0^%xyvHy0m83E? zXU6VOP((p$%**ftJDs z?VTxCXg(an4!xO45;lr4_3Rad{oBa0xl*VIsNTzJO|t?`ZzTPrXL*)=pA$^7BYMTJ zG}kXw$XerVMzf5UT4g6wo_D`mzwfFWasJHrS{|7-I{&INpmHm2NTdBe)QUCl$7*Bn z>SLmM_vbs7N39!wT3qoJ`>R)r^44p2_<_a==-l<4^8{vK@?b7XufDDO%Ln(q;w~zZ z80e_qk1X{u#JPqesQ577kU2#bqc?$Nxm6-3cSTVtVkA>+*=87(LwTifD}kAIn=`yU zZ?F}t^+%$e#dWO?x%!h(P`LxjhxCUd7tgpzq_8#JSd{L^O!!5trg*Q*omZ|e$B29KkhL)E~- z$^$tYvAG(RPc?rtBEntJ7VrAL%3OSNv~d?&cuiF`UWiz}bjuv!S8Z%+Ox;$jM5pGC zzZ5WwR*L#rFbIka@7top70 z=f2XFdumM_bRfki25D6ONL9EUEY$p+N(R2sxqEYe<%D@ifBRhjPgQcnUe={}SBGq~ QL};nX42ZdGAGX~80Ht9l2><{9 literal 0 HcmV?d00001 diff --git a/resources/locales/de_DE/users.po b/resources/locales/de_DE/users.po new file mode 100644 index 000000000..dd14a43b3 --- /dev/null +++ b/resources/locales/de_DE/users.po @@ -0,0 +1,817 @@ +# LANGUAGE translation of CakePHP Application +# Copyright YEAR NAME +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"POT-Creation-Date: 2019-01-10 14:38+0000\n" +"PO-Revision-Date: 2022-03-11 13:31+0100\n" +"Last-Translator: \n" +"Language-Team: LANGUAGE \n" +"Language: de\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 3.0.1\n" + +#: Controller/SocialAccountsController.php:50 +msgid "Account validated successfully" +msgstr "Das Konto wurde erfolgreich bestätigt" + +#: Controller/SocialAccountsController.php:52 +msgid "Account could not be validated" +msgstr "Das Konto konnte nicht bestätigt werden" + +#: Controller/SocialAccountsController.php:55 +msgid "Invalid token and/or social account" +msgstr "Ungültiger Token und/oder Social Account" + +#: Controller/SocialAccountsController.php:57;85 +msgid "Social Account already active" +msgstr "Social Account ist bereits aktiviert" + +#: Controller/SocialAccountsController.php:59 +msgid "Social Account could not be validated" +msgstr "Social Account konnte nicht bestätigt werden" + +#: Controller/SocialAccountsController.php:78 +msgid "Email sent successfully" +msgstr "Email wurde erfolgreich versendet" + +#: Controller/SocialAccountsController.php:80 +msgid "Email could not be sent" +msgstr "Email konnte nicht versendet werden" + +#: Controller/SocialAccountsController.php:83 +msgid "Invalid account" +msgstr "Ungültiges Konto" + +#: Controller/SocialAccountsController.php:87 +msgid "Email could not be resent" +msgstr "Email konnte nicht versendet werden" + +#: Controller/Traits/LinkSocialTrait.php:52 +msgid "Could not associate account, please try again." +msgstr "" +"Wir konnten das Konto leider nicht verbinden, bitte versuchen Sie es erneut." + +#: Controller/Traits/LinkSocialTrait.php:76 +msgid "Social account was associated." +msgstr "Social Account wurde verbunden." + +#: Controller/Traits/LoginTrait.php:73 +msgid "You've successfully logged out" +msgstr "Sie wurden erfolgreich abgemeldet" + +#: Controller/Traits/OneTimePasswordVerifyTrait.php:71 +msgid "Please enable Google Authenticator first." +msgstr "Bitte aktivieren Sie zuerst den Google Authenticator." + +#: Controller/Traits/OneTimePasswordVerifyTrait.php:80 +msgid "Could not find user data" +msgstr "Es konnten keine Benutzer-Daten gefunden werden" + +#: Controller/Traits/OneTimePasswordVerifyTrait.php:116 +msgid "Could not verify, please try again" +msgstr "Überprüfung ist fehlgeschlagen, bitte versuchen Sie es erneut" + +#: Controller/Traits/OneTimePasswordVerifyTrait.php:144 +msgid "Verification code is invalid. Try again" +msgstr "Überprüfungs-Code ist ungültig. Bitte versuchen Sie erneut" + +#: Controller/Traits/PasswordManagementTrait.php:53;91 +#: Controller/Traits/ProfileTrait.php:53 +msgid "User was not found" +msgstr "Der Benutzer konnte nicht gefunden werden" + +#: Controller/Traits/PasswordManagementTrait.php:75;87;95 +msgid "Password could not be changed" +msgstr "Das Passwort konnte nicht geändert werden" + +#: Controller/Traits/PasswordManagementTrait.php:83 +msgid "Password has been changed successfully" +msgstr "Das Passwort wurde erfolgreich geändert" + +#: Controller/Traits/PasswordManagementTrait.php:137 +msgid "Please check your email to continue with password reset process" +msgstr "" +"Sie erhalten in Kürze eine Email mit Anweisungen wie Sie das Passwort " +"zurücksetzen können" + +#: Controller/Traits/PasswordManagementTrait.php:140 Shell/UsersShell.php:247 +msgid "The password token could not be generated. Please try again" +msgstr "" +"Der Token für das Zurücksetzen des Passworts konnte nicht generiert werden. " +"Bitte versuchen Sie es erneut" + +#: Controller/Traits/PasswordManagementTrait.php:146 +#: Controller/Traits/UserValidationTrait.php:116 +msgid "User {0} was not found" +msgstr "Benutzer {0} konnte nicht gefunden werden" + +#: Controller/Traits/PasswordManagementTrait.php:148 +msgid "The user is not active" +msgstr "Der Benutzer ist inaktiv" + +#: Controller/Traits/PasswordManagementTrait.php:150 +#: Controller/Traits/UserValidationTrait.php:111;120 +msgid "Token could not be reset" +msgstr "Der Token konnte nicht zurückgesetzt werden" + +#: Controller/Traits/PasswordManagementTrait.php:174 +msgid "Google Authenticator token was successfully reset" +msgstr "Der Google Authenticator Token wurde erfolgreich zurückgesetzt" + +#: Controller/Traits/ProfileTrait.php:57 +msgid "Not authorized, please login first" +msgstr "" +"Sie sind nicht berechtigt diese Seite aufzurufen. Bitte melden Sie sich " +"zuerst an" + +#: Controller/Traits/RegisterTrait.php:46 +msgid "You must log out to register a new user account" +msgstr "Sie müssen sich ausloggen um ein neues Konto zu erstellen" + +#: Controller/Traits/RegisterTrait.php:75;99 +msgid "The user could not be saved" +msgstr "Der Benutzer konnte nicht gespeichert werden" + +#: Controller/Traits/RegisterTrait.php:92 Loader/LoginComponentLoader.php:32 +msgid "Invalid reCaptcha" +msgstr "Ungültiger reCaptcha" + +#: Controller/Traits/RegisterTrait.php:133 +msgid "You have registered successfully, please log in" +msgstr "Sie haben sich erfolgreich registriert. Bitte melden Sie sich an" + +#: Controller/Traits/RegisterTrait.php:135 +msgid "Please validate your account before log in" +msgstr "Bitte bestätigen Sie ihr Konto bevor Sie sich anmelden" + +#: Controller/Traits/SimpleCrudTrait.php:77;107 +msgid "The {0} has been saved" +msgstr "Der {0} wurde gespeichert" + +#: Controller/Traits/SimpleCrudTrait.php:81;111 +msgid "The {0} could not be saved" +msgstr "Der {0} konnte nicht gespeichert werden" + +#: Controller/Traits/SimpleCrudTrait.php:131 +msgid "The {0} has been deleted" +msgstr "Der {0} wurde gelöscht" + +#: Controller/Traits/SimpleCrudTrait.php:133 +msgid "The {0} could not be deleted" +msgstr "Der {0} konnte nicht gelöscht werden" + +#: Controller/Traits/UserValidationTrait.php:44 +msgid "User account validated successfully" +msgstr "Sie haben Ihren Benutzer erfolgreich bestätigt" + +#: Controller/Traits/UserValidationTrait.php:46 +msgid "User account could not be validated" +msgstr "Ihr Benutzer konnte nicht bestätigt werden" + +#: Controller/Traits/UserValidationTrait.php:49 +msgid "User already active" +msgstr "Dieser Benutzer ist bereits aktiv" + +#: Controller/Traits/UserValidationTrait.php:55 +msgid "Reset password token was validated successfully" +msgstr "Der angegebenen Token für das Zurücksetzen des Passworts ist gültig" + +#: Controller/Traits/UserValidationTrait.php:63 +msgid "Reset password token could not be validated" +msgstr "Der angegebenen Token für das Zurücksetzen des Passworts ist unültig" + +#: Controller/Traits/UserValidationTrait.php:67 +msgid "Invalid validation type" +msgstr "Ungültiger Validierungstyp" + +#: Controller/Traits/UserValidationTrait.php:70 +msgid "Invalid token or user account already validated" +msgstr "Ungültiger Token oder Benutzer ist bereits validiert" + +#: Controller/Traits/UserValidationTrait.php:76 +msgid "Token already expired" +msgstr "Token ist bereits abgelaufen" + +#: Controller/Traits/UserValidationTrait.php:106 +msgid "Token has been reset successfully. Please check your email." +msgstr "" +"Der Token wurde erfolgreich zurückgesetzt. Bitte überprüfen Sie ihren " +"Posteingang." + +#: Controller/Traits/UserValidationTrait.php:118 +msgid "User {0} is already active" +msgstr "Benutzer {0} ist bereits aktiv" + +#: Loader/LoginComponentLoader.php:30 +msgid "Username or password is incorrect" +msgstr "Benutzername oder Passwort ist nicht korrekt" + +#: Loader/LoginComponentLoader.php:51 +msgid "Could not proceed with social account. Please try again" +msgstr "" +"Es konnte keine Verbindung zum Social Account hergestellt werden. Bitte " +"versuchen Sie es erneut" + +#: Loader/LoginComponentLoader.php:53 +msgid "" +"Your user has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Ihr Benutzer wurde noch nicht bestätigt. Bitte überprüfen Sie ihren " +"Posteingang für weitere Anweisungen" + +#: Loader/LoginComponentLoader.php:57 +msgid "" +"Your social account has not been validated yet. Please check your inbox for " +"instructions" +msgstr "" +"Ihr Social Account wurde noch nicht bestätigt. Bitte überprüfen Sie ihren " +"Posteingang für weitere Anweisungen" + +#: Mailer/UsersMailer.php:33 +msgid "Your account validation link" +msgstr "Ihr Konto Validierungs-Link" + +#: Mailer/UsersMailer.php:51 +msgid "{0}Your reset password link" +msgstr "{0}Ihr Passwort Zurücksetzten Link" + +#: Mailer/UsersMailer.php:74 +msgid "{0}Your social account validation link" +msgstr "{0}Ihr Social Account Bestätigung Link" + +#: Middleware/SocialAuthMiddleware.php:65 Template/Users/social_email.ctp:16 +msgid "Please enter your email" +msgstr "Bitte geben Sie ihre E-Mail Adresse ein" + +#: Middleware/SocialAuthMiddleware.php:75 +msgid "Could not identify your account, please try again" +msgstr "" +"Wir konnten Ihr Konto nicht identifizieren. Bitte versuchen Sie es erneut" + +#: Model/Behavior/AuthFinderBehavior.php:48 +msgid "Missing 'username' in options data" +msgstr "Fehlender Parameter ‘username’ in angegeben Optionen" + +#: Model/Behavior/LinkSocialBehavior.php:53 +msgid "Social account already associated to another user" +msgstr "Dieser Social Account ist bereits mit einem anderen Benutzer verknüpft" + +#: Model/Behavior/PasswordBehavior.php:45 +msgid "Reference cannot be null" +msgstr "Referenz darf nicht leer sein" + +#: Model/Behavior/PasswordBehavior.php:50 +msgid "Token expiration cannot be empty" +msgstr "Token Ablaufdatum darf nicht leer sein" + +#: Model/Behavior/PasswordBehavior.php:56;138 +msgid "User not found" +msgstr "Benutzer konnte nicht gefunden werden" + +#: Model/Behavior/PasswordBehavior.php:60 +#: Model/Behavior/RegisterBehavior.php:112 +msgid "User account already validated" +msgstr "Benutzer ist bereits bestätigt" + +#: Model/Behavior/PasswordBehavior.php:67 +msgid "User not active" +msgstr "Benutzer ist nicht aktiv" + +#: Model/Behavior/PasswordBehavior.php:143 +msgid "The current password does not match" +msgstr "Das aktuelle Passwort stimmt nicht überein" + +#: Model/Behavior/PasswordBehavior.php:146 +msgid "You cannot use the current password as the new one" +msgstr "Sie dürfen nicht das aktuelle Passwort als neues Passwort verwenden" + +#: Model/Behavior/RegisterBehavior.php:90 +msgid "User not found for the given token and email." +msgstr "" +"Es konnte kein Benutzer mit dem angegebenen Token oder der angegebenen Email " +"gefunden werden." + +#: Model/Behavior/RegisterBehavior.php:93 +msgid "Token has already expired user with no token" +msgstr "Der Token ist bereits abgelaufen oder der Benutzer hat keinen Token" + +#: Model/Behavior/RegisterBehavior.php:151 +msgid "This field is required" +msgstr "Dieses Feld muss ausgefüllt werden" + +#: Model/Behavior/SocialAccountBehavior.php:102;129 +msgid "Account already validated" +msgstr "Konto ist bereits bestätigt" + +#: Model/Behavior/SocialAccountBehavior.php:105;132 +msgid "Account not found for the given token and email." +msgstr "" +"Es konnte kein Konto für den angegebenen Token oder die angegebene Email " +"gefunden werden." + +#: Model/Behavior/SocialBehavior.php:83 +msgid "Unable to login user with reference {0}" +msgstr "Der Login über die Referenz {0} konnte nicht durchgeführt werden" + +#: Model/Behavior/SocialBehavior.php:122 +msgid "Email not present" +msgstr "Email nicht vorhanden" + +#: Model/Table/UsersTable.php:79 +msgid "Your password does not match your confirm password. Please try again" +msgstr "Bitte bestätigen Sie ihr Passwort und versuchen Sie es erneut" + +#: Model/Table/UsersTable.php:171 +msgid "Username already exists" +msgstr "Benutzername ist bereits vorhanden" + +#: Model/Table/UsersTable.php:177 +msgid "Email already exists" +msgstr "Email ist bereits vorhanden" + +#: Shell/UsersShell.php:58 +msgid "Utilities for CakeDC Users Plugin" +msgstr "Tools für das CakeDC Users Plugin" + +#: Shell/UsersShell.php:60 +msgid "Activate an specific user" +msgstr "Aktiviere einen Benutzer" + +#: Shell/UsersShell.php:63 +msgid "Add a new superadmin user for testing purposes" +msgstr "Füge einen neuen Superadmin Benutzer für Testzwecke hinzu" + +#: Shell/UsersShell.php:66 +msgid "Add a new user" +msgstr "Füge einen neuen Benutzer hinzu" + +#: Shell/UsersShell.php:69 +msgid "Change the role for an specific user" +msgstr "Ändere die Rolle für einen Benutzer" + +#: Shell/UsersShell.php:72 +msgid "Deactivate an specific user" +msgstr "Deaktiviere einen Benutzer" + +#: Shell/UsersShell.php:75 +msgid "Delete an specific user" +msgstr "Lösche einen Benutzer" + +#: Shell/UsersShell.php:78 +msgid "Reset the password via email" +msgstr "Sende Passwort-Zurücksetzen E-Mail für eine E-Mail Adresse" + +#: Shell/UsersShell.php:81 +msgid "Reset the password for all users" +msgstr "Setze das Passwort für alle Benutzer" + +#: Shell/UsersShell.php:84 +msgid "Reset the password for an specific user" +msgstr "Setze das Passwort für einen Benutzer" + +#: Shell/UsersShell.php:133;159 +msgid "Please enter a password." +msgstr "Bitte geben Sie das Passwort ein." + +#: Shell/UsersShell.php:137 +msgid "Password changed for all users" +msgstr "Das Passwort wurde für alle Benutzer geändert" + +#: Shell/UsersShell.php:138;166 +msgid "New password: {0}" +msgstr "Neues Passwort: {0}" + +#: Shell/UsersShell.php:156;184;262;359 +msgid "Please enter a username." +msgstr "Bitte geben Sie einen Benutzernamen ein." + +#: Shell/UsersShell.php:165 +msgid "Password changed for user: {0}" +msgstr "Das Passwort wurde für den Benutzer: {0} geändert" + +#: Shell/UsersShell.php:187 +msgid "Please enter a role." +msgstr "Bitte geben Sie eine Rolle ein." + +#: Shell/UsersShell.php:193 +msgid "Role changed for user: {0}" +msgstr "Die Rolle wurde für den Benutzer: {0} geändert" + +#: Shell/UsersShell.php:194 +msgid "New role: {0}" +msgstr "Neue Rolle: {0}" + +#: Shell/UsersShell.php:209 +msgid "User was activated: {0}" +msgstr "Benutzer wurde aktiviert: {0}" + +#: Shell/UsersShell.php:224 +msgid "User was de-activated: {0}" +msgstr "Benutzer wurde deaktiviert: {0}" + +#: Shell/UsersShell.php:236 +msgid "Please enter a username or email." +msgstr "Bitte geben Sie einen Benutzername oder eine Email ein." + +#: Shell/UsersShell.php:244 +msgid "" +"Please ask the user to check the email to continue with password reset " +"process" +msgstr "" +"Bitte Fragen Sie den Benutzer den Posteingang zu überprüfen für die weitere " +"Vorgehensweise" + +#: Shell/UsersShell.php:308 +msgid "Superuser added:" +msgstr "Superuser hinzugefügt:" + +#: Shell/UsersShell.php:310 +msgid "User added:" +msgstr "Benutzer hinzugefügt:" + +#: Shell/UsersShell.php:312 +msgid "Id: {0}" +msgstr "ID: {0}" + +#: Shell/UsersShell.php:313 +msgid "Username: {0}" +msgstr "Benutzername: {0}" + +#: Shell/UsersShell.php:314 +msgid "Email: {0}" +msgstr "Email: {0}" + +#: Shell/UsersShell.php:315 +msgid "Role: {0}" +msgstr "Rolle: {0}" + +#: Shell/UsersShell.php:316 +msgid "Password: {0}" +msgstr "Passwort: {0}" + +#: Shell/UsersShell.php:318 +msgid "User could not be added:" +msgstr "Benutzer konnte nicht hinzugefügt werden:" + +#: Shell/UsersShell.php:321 +msgid "Field: {0} Error: {1}" +msgstr "Feld: {0} Fehler: {0}" + +#: Shell/UsersShell.php:337 +msgid "The user was not found." +msgstr "Der Benutzer konnte nicht gefunden werden." + +#: Shell/UsersShell.php:367 +msgid "The user {0} was not deleted. Please try again" +msgstr "" +"Der Benutzer {0} konnte nicht gelöscht werden. Bitte versuchen Sie es erneut" + +#: Shell/UsersShell.php:369 +msgid "The user {0} was deleted successfully" +msgstr "Der Benutzer {0} wurde gelöscht" + +#: 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 "Hallo {0}" + +#: Template/Email/html/reset_password.ctp:24 +msgid "Reset your password here" +msgstr "Passwort jetzt zurücksetzen" + +#: 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 "" +"Falls der Link nicht korrekt dargestellt wird kopieren Sie bitte die " +"folgende Adresse in ihren Web Browser {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 "Vielen Dank" + +#: Template/Email/html/social_account_validation.ctp:18 +msgid "Activate your social login here" +msgstr "Social Login aktivieren" + +#: Template/Email/html/validation.ctp:24 +msgid "Activate your account here" +msgstr "Konto aktivieren" + +#: 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 "Bitte kopieren Sie die folgende Adresse in Ihren Web Browser {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 "" +"Bitte kopieren Sie die folgende Adresse in Ihren Web Browser um den Social " +"Login zu aktivieren {0}" + +#: Template/Users/add.ctp:13 Template/Users/edit.ctp:17 +#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 +msgid "Actions" +msgstr "Aktionen" + +#: Template/Users/add.ctp:15 Template/Users/edit.ctp:28 +#: Template/Users/view.ctp:23 +msgid "List Users" +msgstr "Benutzer auflisten" + +#: Template/Users/add.ctp:21 Template/Users/register.ctp:18 +msgid "Add User" +msgstr "Benutzer hinzufügen" + +#: Template/Users/add.ctp:23 Template/Users/edit.ctp:36 +#: Template/Users/index.ctp:22 Template/Users/login.ctp:20 +#: Template/Users/profile.ctp:30 Template/Users/register.ctp:20 +#: Template/Users/view.ctp:33 +msgid "Username" +msgstr "Benutzername" + +#: Template/Users/add.ctp:24 Template/Users/edit.ctp:37 +#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 +#: Template/Users/register.ctp:21 Template/Users/view.ctp:35 +msgid "Email" +msgstr "Email" + +#: Template/Users/add.ctp:25 Template/Users/login.ctp:21 +#: Template/Users/register.ctp:22 +msgid "Password" +msgstr "Passwort" + +#: Template/Users/add.ctp:26 Template/Users/edit.ctp:38 +#: Template/Users/index.ctp:24 Template/Users/register.ctp:27 +msgid "First name" +msgstr "Vorname" + +#: Template/Users/add.ctp:27 Template/Users/edit.ctp:39 +#: Template/Users/index.ctp:25 Template/Users/register.ctp:28 +msgid "Last name" +msgstr "Nachname" + +#: Template/Users/add.ctp:30 Template/Users/edit.ctp:54 +#: Template/Users/view.ctp:49;74 +msgid "Active" +msgstr "Aktiv" + +#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 +#: Template/Users/edit.ctp:58 Template/Users/register.ctp:37 +#: Template/Users/request_reset_password.ctp:8 +#: Template/Users/resend_token_validation.ctp:20 +#: Template/Users/social_email.ctp:19 +msgid "Submit" +msgstr "Absenden" + +#: Template/Users/change_password.ctp:5 +msgid "Please enter the new password" +msgstr "Bitte geben Sie ihr neues Passwort ein" + +#: Template/Users/change_password.ctp:10 +msgid "Current password" +msgstr "Aktuelles Passwort" + +#: Template/Users/change_password.ctp:16 +msgid "New password" +msgstr "Neues Passwort" + +#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:25 +msgid "Confirm password" +msgstr "Neues Passwort bestätigen" + +#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 +msgid "Delete" +msgstr "Löschen" + +#: Template/Users/edit.ctp:24 Template/Users/index.ctp:40 +#: Template/Users/view.ctp:21 +msgid "Are you sure you want to delete # {0}?" +msgstr "Sind Sie sicher, dass Sie # {0} löschen wollen?" + +#: Template/Users/edit.ctp:34 Template/Users/view.ctp:17 +msgid "Edit User" +msgstr "Benutzer bearbeiten" + +#: Template/Users/edit.ctp:40 Template/Users/view.ctp:43 +msgid "Token" +msgstr "Token" + +#: Template/Users/edit.ctp:42 +msgid "Token expires" +msgstr "Token Ablaufdatum" + +#: Template/Users/edit.ctp:45 +msgid "API token" +msgstr "API Token" + +#: Template/Users/edit.ctp:48 +msgid "Activation date" +msgstr "Aktivierungsdatum" + +#: Template/Users/edit.ctp:51 +msgid "TOS date" +msgstr "AGB Datum" + +#: Template/Users/edit.ctp:64 +msgid "Reset Google Authenticator Token" +msgstr "Google Authenticator Token zurücksetzen" + +#: Template/Users/edit.ctp:70 +msgid "Are you sure you want to reset token for user \"{0}\"?" +msgstr "" +"Sind Sie sicher, dass Sie den Token für den Benutzer # {0} zurücksetzen " +"wollen?" + +#: Template/Users/index.ctp:15 +msgid "New {0}" +msgstr "Neuer {0}" + +#: Template/Users/index.ctp:37 +msgid "View" +msgstr "Ansicht" + +#: Template/Users/index.ctp:38 +msgid "Change password" +msgstr "Passwort ändern" + +#: Template/Users/index.ctp:39 +msgid "Edit" +msgstr "Bearbeiten" + +#: Template/Users/index.ctp:49 +msgid "previous" +msgstr "vorherig" + +#: Template/Users/index.ctp:51 +msgid "next" +msgstr "nächste" + +#: Template/Users/login.ctp:19 +msgid "Please enter your username and password" +msgstr "Bitte geben Sie ihren Benutzernamen und Passwort ein" + +#: Template/Users/login.ctp:29 +msgid "Remember me" +msgstr "Angemeldet bleiben" + +#: Template/Users/login.ctp:37 +msgid "Register" +msgstr "Registrieren" + +#: Template/Users/login.ctp:43 +msgid "Reset Password" +msgstr "Passwort zurücksetzen" + +#: Template/Users/login.ctp:48 +msgid "Login" +msgstr "Anmelden" + +#: Template/Users/profile.ctp:21 +msgid "{0} {1}" +msgstr "{0} {1}" + +#: Template/Users/profile.ctp:27 +msgid "Change Password" +msgstr "Passwort ändern" + +#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 +msgid "Social Accounts" +msgstr "Social Accounts" + +#: 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 "Provider" + +#: Template/Users/profile.ctp:44 +msgid "Link" +msgstr "Link" + +#: Template/Users/profile.ctp:51 +msgid "Link to {0}" +msgstr "Link zu {0}" + +#: Template/Users/register.ctp:30 +msgid "Accept TOS conditions?" +msgstr "AGBs akzeptieren?" + +#: Template/Users/request_reset_password.ctp:5 +msgid "Please enter your email to reset your password" +msgstr "Bitte geben Sie ihre Email Adresse ein um ihr Passwort zurückzusetzen" + +#: Template/Users/resend_token_validation.ctp:15 +msgid "Resend Validation email" +msgstr "Validierungs-Email erneut versenden" + +#: Template/Users/resend_token_validation.ctp:17 +msgid "Email or username" +msgstr "Email oder Benutzername" + +#: Template/Users/verify.ctp:13 +msgid "Verification Code" +msgstr "Bestätigungscode" + +#: Template/Users/verify.ctp:15 +msgid "" +" " +"Verify" +msgstr "" +" " +"Bestätigen" + +#: Template/Users/view.ctp:19 +msgid "Delete User" +msgstr "Benutzer löschen" + +#: Template/Users/view.ctp:24 +msgid "New User" +msgstr "Benutzer hinzufügen" + +#: Template/Users/view.ctp:31 +msgid "Id" +msgstr "ID" + +#: Template/Users/view.ctp:37 +msgid "First Name" +msgstr "Vorname" + +#: Template/Users/view.ctp:39 +msgid "Last Name" +msgstr "Nachname" + +#: Template/Users/view.ctp:41 +msgid "Role" +msgstr "Rolle" + +#: Template/Users/view.ctp:45 +msgid "Api Token" +msgstr "API Token" + +#: Template/Users/view.ctp:53 +msgid "Token Expires" +msgstr "Token Ablaufdatum" + +#: Template/Users/view.ctp:55 +msgid "Activation Date" +msgstr "Aktivierungsdatum" + +#: Template/Users/view.ctp:57 +msgid "Tos Date" +msgstr "AGB Datum" + +#: Template/Users/view.ctp:59;75 +msgid "Created" +msgstr "erstellt am" + +#: Template/Users/view.ctp:61;76 +msgid "Modified" +msgstr "zuletzt aktualisiert" + +#: View/Helper/UserHelper.php:46 +msgid "Sign in with" +msgstr "Anmelden mit" + +#: View/Helper/UserHelper.php:103 +msgid "Logout" +msgstr "Abmelden" + +#: View/Helper/UserHelper.php:121 +msgid "Welcome, {0}" +msgstr "Willkommen, {0}" + +#: View/Helper/UserHelper.php:151 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"reCaptcha ist nicht konfiguriert! Bitte setzten Sie Users.reCaptcha.key" + +#: View/Helper/UserHelper.php:215 +msgid "Connected with {0}" +msgstr "Mit {0} verbunden" + +#: View/Helper/UserHelper.php:220 +msgid "Connect with {0}" +msgstr "Mit {0} verbinden" From c18b32bb11df611d9916fd8d2d8ebbbf70ec7dac Mon Sep 17 00:00:00 2001 From: Kevin Pfeifer Date: Fri, 11 Mar 2022 14:23:13 +0100 Subject: [PATCH 682/685] fix not all translations using __d() function and update .pot file --- resources/locales/de_DE/users.mo | Bin 15667 -> 18251 bytes resources/locales/de_DE/users.po | 636 ++++++++++++-------- resources/locales/users.pot | 644 ++++++++++++--------- src/Controller/Traits/Webauthn2faTrait.php | 4 +- src/Loader/AuthenticationServiceLoader.php | 2 +- templates/Users/u2f_authenticate.php | 2 +- templates/Users/webauthn2fa.php | 4 +- 7 files changed, 767 insertions(+), 525 deletions(-) diff --git a/resources/locales/de_DE/users.mo b/resources/locales/de_DE/users.mo index 61a8ac7065103115bcd5a87e1a3a01659e891cac..8408ca51fb24120d9ddbe4f1407ff9722252af11 100644 GIT binary patch delta 6450 zcmZ9N3v?9K9fxl)pnw*FA_OH|2#|;&kTgPxA_NgcDMEum#Hy3s+1)Xl*>rZ7nAp0O z)>=WKb$wLSTB~hsEh=u2N@=U6)MwAJw(9BQXl>82w#Pn>mA1<11;TW`zCk_TngpTW;h;R0jIz$tcIV3W7*%_z+f~iL)J8R zK!xlfs1KfjMA7^v<~#9xHF+4v{Hc&B(-7Y;jd>oF;hj*1Tn9(N8=+FO3zi%Pw=-A^ z--8O>Dt6U|U9cWzph9*dZA>DJT4xDd2Uo*o z@HV&!zEVs4moR9iG*u)S$hYQZs8l=%71}4@O!!Lt{GU)8)sSeMGz(xmTn!uGHaG`< z3(kWtLal!U%J4a~n)YcfG0?~wA*jf_2~UTIp;9yx zt1R3AWk>*dWOhSsxF0H2FG74UrI#5fmw$yy!TXRub1ZR{2Xmlm;sU5*+5-7AH}N9_ zzYSIO6(~o31hw8zplat;cqTjo<=EmG(fQE{aj0ajWT1_ix-38!v^5SQk`^Qc$TaLZ$FND964BC$YbIg@JPThxox{ zcB2!`LKxNt)Q9UKdzuWCN8983FF_f80LqXT;`w)>a((jbD7B}+N4Rf|PDehBEvd*a6qVW8qGy8n_Me ziFvev__tPJ2@@AGar|jf@mvb!Q3`6~t6(F%6mxxPZ26~JK#)sAJjsJ;^!|y zNTA$1PO0xC(vJJ;kpK0TVaxod$2+QyUco2RZJ_j#_jcpVnybdmhZ$UYD8b6Bc3<%)K@J_fIJ_=XC_o1r1gMXbeFb&UwJE7Y3d8lH0 z3zBa0XQ&#Q(HzH}!86~`es z3%&%k(P1c$XJMx1+o0|@L7X!llp)`M>hqVNQus^w6#OG>fqMwYCGd5q{~hi8EQcjX zc1z|71~ZvB0#AX{&*dKoTmnAu# zg1QtTT^xqy>TpzwDqZ8xpsT{k=;zsZd?A!ay1s>WpzD$9M8&HxKY^4kopi(3Xa*-D zb-``V`uZQs_(QV)QknD}hwmV|2rH0Bu2+p$f_& z9Zn~p+tKHd(t0P-wL3!Cehf?DQEB5z;Y>sqny1k~cqw~?ucur^;F@7i>pBJ$do_2R|^AWTO{V;l9J`KNs9!Ce`xot7O9e2n-5yoIDIu_~Lht5V#=w9>)%A)e#`g1FLCR|@t*XP+n zuE+IlBIEdJH)&J3z!vjv&~C3@_^EPh&8|A<=sSAm_%`3?CcKoF2;VF3t7&M~x1OKo zVXlyIqXioBw$I7u`*T6kdU?we>twUJem7bEWz9R&0ypm#?CM-Dopo(Tk{j%k@)tjE{ZwonE)RXX@%Y&&PA@^pm#W^hH|^ zuw^1=d)$HY+fx_JWs|~yRdAXUS^Qhaw>F>26|+g(?b@W9@_byJQro;vHsFFA1nkrA z6*9Kp?RIe0KN@B0CBs0QkA)Vyfub0C`oXq5%jTS9Wkv1o>eDy&=jNxJ1YxpTDGnNL znu}Uj;rAzs9+9=3ook!RznZ>pmXi%!Cplm4wyuoPAE1X0kvehZrY>tXmjfEd1=nX&DPht9AJ`?Wxzd6FqT=;P@ zFCS#qh!7^-tzN=yt~A*1SIw6tQPsuCPy$nqmsNWDvaW+WgH} z^vm+LxeXni9@WiyDIWMI&{7=x~cA%Xjophps~DQ!QM$Z9Vx@{P}lqA*B4w7ZcDIrusA+Fo6vz+ z7bmzrN39v(#qT^cX<@xL!H8a8c=8ikag_5wWY>OqOlCU5^(7 z8+CfX>qTlHNwaQ>PX(IMh8ar|kYOwBnw8-RLA$3+Top2Oq}yhlTeMk+c$p3k@m{y` z;KI%^tvV}KMQ6qE0h{s$qm9Gkf)jX<@OQ2ydx2BTH<$ml=)Jis72XfR#L-c}_`v0m z9bswZFN+sfl{0N8ly|mGC|`WW#B#@3C)UxouIX$TE&0FE- z3q$u8ytD!r*4YQX(3~T(QC{C(TiWFM90wRQTpW&{qN36T3LrW`_$C<)9SpOk`snrw zN(!UsFmdflFW=*8ve-+dsdTKSAjW#|Jdt6qnVWQU_g++04XsdbByX~X607v&Re7oXur^TN_W zZcqn|IwMIt{cmtqy8*GYDT>WYQ>xjlsy@>`ebk&0#W8dj3F{*!Db<*Akan>&>!iy! MHOwksch*Dy1sVdSX8-^I delta 4178 zcmY+_3s6->9LMp!2nvCMAc_}M@QF`E1p-V!0U!BJ6VOspQ1XFMhLU-;GGD3b5wY-* zsijF49djBTYbG;iGNckj~F4*&DnJ@?+TyZ_xioZaMcYkZ$Z z2iF?PF(QF@GsKu{xICN-WnQE)W3U3l@F=#&m$4(hkDc){4#YN5fp!kIqJ2B+d*$fG zmDmOAk)Qa?i9p4i#g=?<0YmXi9Dv_r8}zmf44^mmq&*miUjp;V9Z{ts}E?O#vAYxjKyzl`?@uZr)j|LPy;E%ARLDp z@I)-dB2;FMqxyLRyI~XhQmE+Z>Tn=x#G|Z}Q8Sr=nqetwKnqbbT8ip;1u9dkQA>Bw z+K3UfkE1$1gRSu+)BrEWl7Id1GB@+}~z-}Cm4VZ)1a2jSa zi%fK|H=aW+?H|ZwO%#nJ?18#JGLHPKgITorj#+`)blb5Pp2j|S2{pht7LKY(LbbC{ znHhol{RB+Jxu{LM7W-lyD$}Rz=f9$!-_FOG(6JkedT=o++*gDLD#EzNk;rk#o!a5?IEm8d=7TSg_D$}Z&3e8h!pn%__}iePl= zs5>e%V^9NL#)ZDjcGSQdQNMe``UPr_TtzL}b!3%I1f$pYyJDiwe>N3;VFvcYJ24yU zP$Pa9m8vGx%!0XScmkj9#7pur7fYLU+`R zGEg&_j2b`%>IYS*&9fdg;0D`1j@sQ#sDb{7TEg~;fhCK_L9~-mdtkbC19tXt;{+A5 zV?M@w`~!<{D7}rxTGRu-LJjCU%)?)>6%OGDv07#*>Xa1WAP>343AA4zU0U;??ty_u zp!(~KzGN!dR7!9T>H)8yI{F5c%FC!t6v{?WCOV>KoN66`A+)EWj@fk75-!F>Y(Nd* z91g_uI0-|0l7H>e5_(k!rPeCsJLW<3;vrOruUS99v9!NMr8JGakH#{biO*pUMlw6? zjS0xx+Du11ZxM##x@7XN2XEzu)_gze4R->ynO?^b{1}zu&rzH2PitcDz^=|mWu^pK z6;p+J&Nln`9@J93Xg!G<;AtO~Fe)LuWr8pg^~GphgkIDD*P)J2J@OONh-r8MHL$k4 zWkRvPH64R#=U_PIqcSiN^}X3v-vTN(a$^Z>JHIrAcEuKcr@I0!cE2s=4r3XGAg(GN};8fg=8t@eyj@MBW%VRw> z@KR)z%*G7z-=4}zZfLFFLyi1*)J&4tnHq5xYSYX@t>Me42R5Nj!=K3O-1N*0vsO# zce*mPooG!Qv-h9FF~n@!W~=!pREx@-??L;)2vOryLCbvc#hHgUWb9OQbSU=bz1N9wn9$MZ^+9n`;}fhPajB-QzFmTxSta6ZaF% zWiFLS+o(tXxyRl1o^Xgg|7q(4jirBo*~E3Lt!rbAA|57M*n1pZe_>ylIYcKyJ9`qL zqTQ{c&88#9f$$&UmDpT%*vd1_H_+E$8;5WyF_V}=v?7|zPAXFg9mN&)rjF^IL?cm7 zc!?_F01-~~Cz?wbm2tMw5+5Vt1MR^4YiQg<nIeF^@_ZYD+& zg~TmHbBU&MA2E$sWN+@W#$hqBn9%$GA!0g_O8C?KJUZdM3*2#S*La*O(Hot^G4amt zF+aKCu|Ij-Q5{k|?!$4TgPgCuHO~C_Lg##ZFDE&nkGn6SF4!qgI_eDX+TeJ*U5KhE zt2Wch7R;_(Sk^D`zJd3Bsv~Rt0Q@>8`&VJ<{ zH+MiykQjn2XJnNCVZnzJP%)y=-KxTSMu*j1-KFU-lzZS4l- YdOhy)yuKdio#AnAR(?W|v#apPKTQ0z_5c6? diff --git a/resources/locales/de_DE/users.po b/resources/locales/de_DE/users.po index dd14a43b3..7e9a16bce 100644 --- a/resources/locales/de_DE/users.po +++ b/resources/locales/de_DE/users.po @@ -4,8 +4,8 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2019-01-10 14:38+0000\n" -"PO-Revision-Date: 2022-03-11 13:31+0100\n" +"POT-Creation-Date: 2022-03-11 13:46+0100\n" +"PO-Revision-Date: 2022-03-11 14:19+0100\n" "Last-Translator: \n" "Language-Team: LANGUAGE \n" "Language: de\n" @@ -15,209 +15,247 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 3.0.1\n" -#: Controller/SocialAccountsController.php:50 +#: src/Controller/SocialAccountsController.php:50 msgid "Account validated successfully" msgstr "Das Konto wurde erfolgreich bestätigt" -#: Controller/SocialAccountsController.php:52 +#: src/Controller/SocialAccountsController.php:52 msgid "Account could not be validated" msgstr "Das Konto konnte nicht bestätigt werden" -#: Controller/SocialAccountsController.php:55 +#: src/Controller/SocialAccountsController.php:55 msgid "Invalid token and/or social account" msgstr "Ungültiger Token und/oder Social Account" -#: Controller/SocialAccountsController.php:57;85 +#: src/Controller/SocialAccountsController.php:57 +#: src/Controller/SocialAccountsController.php:85 msgid "Social Account already active" msgstr "Social Account ist bereits aktiviert" -#: Controller/SocialAccountsController.php:59 +#: src/Controller/SocialAccountsController.php:59 msgid "Social Account could not be validated" msgstr "Social Account konnte nicht bestätigt werden" -#: Controller/SocialAccountsController.php:78 +#: src/Controller/SocialAccountsController.php:78 msgid "Email sent successfully" msgstr "Email wurde erfolgreich versendet" -#: Controller/SocialAccountsController.php:80 +#: src/Controller/SocialAccountsController.php:80 msgid "Email could not be sent" msgstr "Email konnte nicht versendet werden" -#: Controller/SocialAccountsController.php:83 +#: src/Controller/SocialAccountsController.php:83 msgid "Invalid account" msgstr "Ungültiges Konto" -#: Controller/SocialAccountsController.php:87 +#: src/Controller/SocialAccountsController.php:87 msgid "Email could not be resent" msgstr "Email konnte nicht versendet werden" -#: Controller/Traits/LinkSocialTrait.php:52 +#: src/Controller/Traits/LinkSocialTrait.php:56 msgid "Could not associate account, please try again." msgstr "" "Wir konnten das Konto leider nicht verbinden, bitte versuchen Sie es erneut." -#: Controller/Traits/LinkSocialTrait.php:76 +#: src/Controller/Traits/LinkSocialTrait.php:80 msgid "Social account was associated." msgstr "Social Account wurde verbunden." -#: Controller/Traits/LoginTrait.php:73 +#: src/Controller/Traits/LoginTrait.php:73 msgid "You've successfully logged out" msgstr "Sie wurden erfolgreich abgemeldet" -#: Controller/Traits/OneTimePasswordVerifyTrait.php:71 +#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:75 msgid "Please enable Google Authenticator first." msgstr "Bitte aktivieren Sie zuerst den Google Authenticator." -#: Controller/Traits/OneTimePasswordVerifyTrait.php:80 +#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:90 msgid "Could not find user data" msgstr "Es konnten keine Benutzer-Daten gefunden werden" -#: Controller/Traits/OneTimePasswordVerifyTrait.php:116 +#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:129 msgid "Could not verify, please try again" msgstr "Überprüfung ist fehlgeschlagen, bitte versuchen Sie es erneut" -#: Controller/Traits/OneTimePasswordVerifyTrait.php:144 +#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:161 msgid "Verification code is invalid. Try again" msgstr "Überprüfungs-Code ist ungültig. Bitte versuchen Sie erneut" -#: Controller/Traits/PasswordManagementTrait.php:53;91 -#: Controller/Traits/ProfileTrait.php:53 +#: src/Controller/Traits/PasswordManagementTrait.php:63 +msgid "Changing another user's password is not allowed" +msgstr "Sie dürfen nicht das Passwort von einem anderen Benutzer ändern" + +#: src/Controller/Traits/PasswordManagementTrait.php:77 +#: src/Controller/Traits/PasswordManagementTrait.php:121 +#: src/Controller/Traits/ProfileTrait.php:54 msgid "User was not found" msgstr "Der Benutzer konnte nicht gefunden werden" -#: Controller/Traits/PasswordManagementTrait.php:75;87;95 +#: src/Controller/Traits/PasswordManagementTrait.php:105 +#: src/Controller/Traits/PasswordManagementTrait.php:117 +#: src/Controller/Traits/PasswordManagementTrait.php:125 msgid "Password could not be changed" msgstr "Das Passwort konnte nicht geändert werden" -#: Controller/Traits/PasswordManagementTrait.php:83 +#: src/Controller/Traits/PasswordManagementTrait.php:113 msgid "Password has been changed successfully" msgstr "Das Passwort wurde erfolgreich geändert" -#: Controller/Traits/PasswordManagementTrait.php:137 +#: src/Controller/Traits/PasswordManagementTrait.php:167 msgid "Please check your email to continue with password reset process" msgstr "" "Sie erhalten in Kürze eine Email mit Anweisungen wie Sie das Passwort " "zurücksetzen können" -#: Controller/Traits/PasswordManagementTrait.php:140 Shell/UsersShell.php:247 +#: src/Controller/Traits/PasswordManagementTrait.php:170 +#: src/Shell/UsersShell.php:286 msgid "The password token could not be generated. Please try again" msgstr "" "Der Token für das Zurücksetzen des Passworts konnte nicht generiert werden. " "Bitte versuchen Sie es erneut" -#: Controller/Traits/PasswordManagementTrait.php:146 -#: Controller/Traits/UserValidationTrait.php:116 +#: src/Controller/Traits/PasswordManagementTrait.php:176 +#: src/Controller/Traits/UserValidationTrait.php:124 msgid "User {0} was not found" msgstr "Benutzer {0} konnte nicht gefunden werden" -#: Controller/Traits/PasswordManagementTrait.php:148 +#: src/Controller/Traits/PasswordManagementTrait.php:178 msgid "The user is not active" msgstr "Der Benutzer ist inaktiv" -#: Controller/Traits/PasswordManagementTrait.php:150 -#: Controller/Traits/UserValidationTrait.php:111;120 +#: src/Controller/Traits/PasswordManagementTrait.php:180 +#: src/Controller/Traits/UserValidationTrait.php:119 +#: src/Controller/Traits/UserValidationTrait.php:128 msgid "Token could not be reset" msgstr "Der Token konnte nicht zurückgesetzt werden" -#: Controller/Traits/PasswordManagementTrait.php:174 +#: src/Controller/Traits/PasswordManagementTrait.php:204 msgid "Google Authenticator token was successfully reset" msgstr "Der Google Authenticator Token wurde erfolgreich zurückgesetzt" -#: Controller/Traits/ProfileTrait.php:57 +#: src/Controller/Traits/PasswordManagementTrait.php:207 +msgid "Could not reset Google Authenticator" +msgstr "Google Authenticator Token konnte nicht zurückgesetzt werden" + +#: src/Controller/Traits/ProfileTrait.php:58 msgid "Not authorized, please login first" msgstr "" "Sie sind nicht berechtigt diese Seite aufzurufen. Bitte melden Sie sich " "zuerst an" -#: Controller/Traits/RegisterTrait.php:46 +#: src/Controller/Traits/RegisterTrait.php:47 msgid "You must log out to register a new user account" msgstr "Sie müssen sich ausloggen um ein neues Konto zu erstellen" -#: Controller/Traits/RegisterTrait.php:75;99 +#: src/Controller/Traits/RegisterTrait.php:86 +#: src/Controller/Traits/RegisterTrait.php:117 msgid "The user could not be saved" msgstr "Der Benutzer konnte nicht gespeichert werden" -#: Controller/Traits/RegisterTrait.php:92 Loader/LoginComponentLoader.php:32 +#: src/Controller/Traits/RegisterTrait.php:103 +#: src/Loader/LoginComponentLoader.php:33 msgid "Invalid reCaptcha" msgstr "Ungültiger reCaptcha" -#: Controller/Traits/RegisterTrait.php:133 +#: src/Controller/Traits/RegisterTrait.php:151 msgid "You have registered successfully, please log in" msgstr "Sie haben sich erfolgreich registriert. Bitte melden Sie sich an" -#: Controller/Traits/RegisterTrait.php:135 +#: src/Controller/Traits/RegisterTrait.php:153 msgid "Please validate your account before log in" msgstr "Bitte bestätigen Sie ihr Konto bevor Sie sich anmelden" -#: Controller/Traits/SimpleCrudTrait.php:77;107 +#: src/Controller/Traits/SimpleCrudTrait.php:77 +#: src/Controller/Traits/SimpleCrudTrait.php:107 msgid "The {0} has been saved" msgstr "Der {0} wurde gespeichert" -#: Controller/Traits/SimpleCrudTrait.php:81;111 +#: src/Controller/Traits/SimpleCrudTrait.php:81 +#: src/Controller/Traits/SimpleCrudTrait.php:111 msgid "The {0} could not be saved" msgstr "Der {0} konnte nicht gespeichert werden" -#: Controller/Traits/SimpleCrudTrait.php:131 +#: src/Controller/Traits/SimpleCrudTrait.php:131 msgid "The {0} has been deleted" msgstr "Der {0} wurde gelöscht" -#: Controller/Traits/SimpleCrudTrait.php:133 +#: src/Controller/Traits/SimpleCrudTrait.php:133 msgid "The {0} could not be deleted" msgstr "Der {0} konnte nicht gelöscht werden" -#: Controller/Traits/UserValidationTrait.php:44 +#: src/Controller/Traits/U2fTrait.php:216 +msgid "U2F requires SSL." +msgstr "U2F setzt SSL voraus." + +#: src/Controller/Traits/UserValidationTrait.php:49 msgid "User account validated successfully" msgstr "Sie haben Ihren Benutzer erfolgreich bestätigt" -#: Controller/Traits/UserValidationTrait.php:46 +#: src/Controller/Traits/UserValidationTrait.php:51 msgid "User account could not be validated" msgstr "Ihr Benutzer konnte nicht bestätigt werden" -#: Controller/Traits/UserValidationTrait.php:49 +#: src/Controller/Traits/UserValidationTrait.php:54 msgid "User already active" msgstr "Dieser Benutzer ist bereits aktiv" -#: Controller/Traits/UserValidationTrait.php:55 +#: src/Controller/Traits/UserValidationTrait.php:60 msgid "Reset password token was validated successfully" msgstr "Der angegebenen Token für das Zurücksetzen des Passworts ist gültig" -#: Controller/Traits/UserValidationTrait.php:63 +#: src/Controller/Traits/UserValidationTrait.php:68 msgid "Reset password token could not be validated" msgstr "Der angegebenen Token für das Zurücksetzen des Passworts ist unültig" -#: Controller/Traits/UserValidationTrait.php:67 +#: src/Controller/Traits/UserValidationTrait.php:72 msgid "Invalid validation type" msgstr "Ungültiger Validierungstyp" -#: Controller/Traits/UserValidationTrait.php:70 +#: src/Controller/Traits/UserValidationTrait.php:75 msgid "Invalid token or user account already validated" msgstr "Ungültiger Token oder Benutzer ist bereits validiert" -#: Controller/Traits/UserValidationTrait.php:76 +#: src/Controller/Traits/UserValidationTrait.php:81 msgid "Token already expired" msgstr "Token ist bereits abgelaufen" -#: Controller/Traits/UserValidationTrait.php:106 +#: src/Controller/Traits/UserValidationTrait.php:114 msgid "Token has been reset successfully. Please check your email." msgstr "" "Der Token wurde erfolgreich zurückgesetzt. Bitte überprüfen Sie ihren " "Posteingang." -#: Controller/Traits/UserValidationTrait.php:118 +#: src/Controller/Traits/UserValidationTrait.php:126 msgid "User {0} is already active" msgstr "Benutzer {0} ist bereits aktiv" -#: Loader/LoginComponentLoader.php:30 +#: src/Controller/Traits/Webauthn2faTrait.php:53 +#: src/Controller/Traits/Webauthn2faTrait.php:73 +msgid "User already has configured webauthn2fa" +msgstr "Dieser Benutzer hat bereis Webauthn2fa aktiv" + +#: src/Controller/Traits/Webauthn2faTrait.php:77 +#: src/Controller/Traits/Webauthn2faTrait.php:122 +msgid "Register error with webauthn for user id: {0}" +msgstr "" +"Es trat ein Fehler bei der Registrierung des Webauthn2fa für die Benutzer " +"ID: {0} auf" + +#: src/Loader/AuthenticationServiceLoader.php:109 +msgid "Property {0}.className should be defined" +msgstr "Property {0}.className sollte definiert sein" + +#: src/Loader/LoginComponentLoader.php:31 msgid "Username or password is incorrect" msgstr "Benutzername oder Passwort ist nicht korrekt" -#: Loader/LoginComponentLoader.php:51 +#: src/Loader/LoginComponentLoader.php:52 msgid "Could not proceed with social account. Please try again" msgstr "" "Es konnte keine Verbindung zum Social Account hergestellt werden. Bitte " "versuchen Sie es erneut" -#: Loader/LoginComponentLoader.php:53 +#: src/Loader/LoginComponentLoader.php:54 msgid "" "Your user has not been validated yet. Please check your inbox for " "instructions" @@ -225,7 +263,7 @@ msgstr "" "Ihr Benutzer wurde noch nicht bestätigt. Bitte überprüfen Sie ihren " "Posteingang für weitere Anweisungen" -#: Loader/LoginComponentLoader.php:57 +#: src/Loader/LoginComponentLoader.php:58 msgid "" "Your social account has not been validated yet. Please check your inbox for " "instructions" @@ -233,193 +271,225 @@ msgstr "" "Ihr Social Account wurde noch nicht bestätigt. Bitte überprüfen Sie ihren " "Posteingang für weitere Anweisungen" -#: Mailer/UsersMailer.php:33 +#: src/Mailer/UsersMailer.php:36 msgid "Your account validation link" msgstr "Ihr Konto Validierungs-Link" -#: Mailer/UsersMailer.php:51 +#: src/Mailer/UsersMailer.php:63 msgid "{0}Your reset password link" msgstr "{0}Ihr Passwort Zurücksetzten Link" -#: Mailer/UsersMailer.php:74 +#: src/Mailer/UsersMailer.php:95 msgid "{0}Your social account validation link" msgstr "{0}Ihr Social Account Bestätigung Link" -#: Middleware/SocialAuthMiddleware.php:65 Template/Users/social_email.ctp:16 +#: src/Middleware/SocialAuthMiddleware.php:47 +#: templates/Users/social_email.php:16 msgid "Please enter your email" msgstr "Bitte geben Sie ihre E-Mail Adresse ein" -#: Middleware/SocialAuthMiddleware.php:75 +#: src/Middleware/SocialAuthMiddleware.php:57 msgid "Could not identify your account, please try again" msgstr "" "Wir konnten Ihr Konto nicht identifizieren. Bitte versuchen Sie es erneut" -#: Model/Behavior/AuthFinderBehavior.php:48 +#: src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php:112 +msgid "You are not authorized to access that location." +msgstr "Sie sind nicht berechtigt diese Seite aufzurufen." + +#: src/Model/Behavior/AuthFinderBehavior.php:49 msgid "Missing 'username' in options data" msgstr "Fehlender Parameter ‘username’ in angegeben Optionen" -#: Model/Behavior/LinkSocialBehavior.php:53 +#: src/Model/Behavior/LinkSocialBehavior.php:52 msgid "Social account already associated to another user" msgstr "Dieser Social Account ist bereits mit einem anderen Benutzer verknüpft" -#: Model/Behavior/PasswordBehavior.php:45 +#: src/Model/Behavior/PasswordBehavior.php:45 msgid "Reference cannot be null" msgstr "Referenz darf nicht leer sein" -#: Model/Behavior/PasswordBehavior.php:50 +#: src/Model/Behavior/PasswordBehavior.php:50 msgid "Token expiration cannot be empty" msgstr "Token Ablaufdatum darf nicht leer sein" -#: Model/Behavior/PasswordBehavior.php:56;138 +#: src/Model/Behavior/PasswordBehavior.php:56 +#: src/Model/Behavior/PasswordBehavior.php:136 msgid "User not found" msgstr "Benutzer konnte nicht gefunden werden" -#: Model/Behavior/PasswordBehavior.php:60 -#: Model/Behavior/RegisterBehavior.php:112 +#: src/Model/Behavior/PasswordBehavior.php:60 +#: src/Model/Behavior/RegisterBehavior.php:129 msgid "User account already validated" msgstr "Benutzer ist bereits bestätigt" -#: Model/Behavior/PasswordBehavior.php:67 +#: src/Model/Behavior/PasswordBehavior.php:66 msgid "User not active" msgstr "Benutzer ist nicht aktiv" -#: Model/Behavior/PasswordBehavior.php:143 +#: src/Model/Behavior/PasswordBehavior.php:141 msgid "The current password does not match" msgstr "Das aktuelle Passwort stimmt nicht überein" -#: Model/Behavior/PasswordBehavior.php:146 +#: src/Model/Behavior/PasswordBehavior.php:144 msgid "You cannot use the current password as the new one" msgstr "Sie dürfen nicht das aktuelle Passwort als neues Passwort verwenden" -#: Model/Behavior/RegisterBehavior.php:90 +#: src/Model/Behavior/RegisterBehavior.php:107 msgid "User not found for the given token and email." msgstr "" "Es konnte kein Benutzer mit dem angegebenen Token oder der angegebenen Email " "gefunden werden." -#: Model/Behavior/RegisterBehavior.php:93 +#: src/Model/Behavior/RegisterBehavior.php:110 msgid "Token has already expired user with no token" msgstr "Der Token ist bereits abgelaufen oder der Benutzer hat keinen Token" -#: Model/Behavior/RegisterBehavior.php:151 +#: src/Model/Behavior/RegisterBehavior.php:167 msgid "This field is required" msgstr "Dieses Feld muss ausgefüllt werden" -#: Model/Behavior/SocialAccountBehavior.php:102;129 +#: src/Model/Behavior/SocialAccountBehavior.php:100 +#: src/Model/Behavior/SocialAccountBehavior.php:130 msgid "Account already validated" msgstr "Konto ist bereits bestätigt" -#: Model/Behavior/SocialAccountBehavior.php:105;132 +#: src/Model/Behavior/SocialAccountBehavior.php:104 +#: src/Model/Behavior/SocialAccountBehavior.php:135 msgid "Account not found for the given token and email." msgstr "" "Es konnte kein Konto für den angegebenen Token oder die angegebene Email " "gefunden werden." -#: Model/Behavior/SocialBehavior.php:83 +#: src/Model/Behavior/SocialBehavior.php:85 msgid "Unable to login user with reference {0}" msgstr "Der Login über die Referenz {0} konnte nicht durchgeführt werden" -#: Model/Behavior/SocialBehavior.php:122 +#: src/Model/Behavior/SocialBehavior.php:136 msgid "Email not present" msgstr "Email nicht vorhanden" -#: Model/Table/UsersTable.php:79 +#: src/Model/Table/UsersTable.php:107 msgid "Your password does not match your confirm password. Please try again" msgstr "Bitte bestätigen Sie ihr Passwort und versuchen Sie es erneut" -#: Model/Table/UsersTable.php:171 +#: src/Model/Table/UsersTable.php:201 msgid "Username already exists" msgstr "Benutzername ist bereits vorhanden" -#: Model/Table/UsersTable.php:177 +#: src/Model/Table/UsersTable.php:207 msgid "Email already exists" msgstr "Email ist bereits vorhanden" -#: Shell/UsersShell.php:58 +#: src/Shell/UsersShell.php:46 msgid "Utilities for CakeDC Users Plugin" msgstr "Tools für das CakeDC Users Plugin" -#: Shell/UsersShell.php:60 +#: src/Shell/UsersShell.php:48 msgid "Activate an specific user" msgstr "Aktiviere einen Benutzer" -#: Shell/UsersShell.php:63 +#: src/Shell/UsersShell.php:51 msgid "Add a new superadmin user for testing purposes" msgstr "Füge einen neuen Superadmin Benutzer für Testzwecke hinzu" -#: Shell/UsersShell.php:66 +#: src/Shell/UsersShell.php:54 msgid "Add a new user" msgstr "Füge einen neuen Benutzer hinzu" -#: Shell/UsersShell.php:69 +#: src/Shell/UsersShell.php:57 msgid "Change the role for an specific user" msgstr "Ändere die Rolle für einen Benutzer" -#: Shell/UsersShell.php:72 +#: src/Shell/UsersShell.php:60 +msgid "Change the api token for an specific user" +msgstr "Ändere den API Token für einen Benutzer" + +#: src/Shell/UsersShell.php:63 msgid "Deactivate an specific user" msgstr "Deaktiviere einen Benutzer" -#: Shell/UsersShell.php:75 +#: src/Shell/UsersShell.php:66 msgid "Delete an specific user" msgstr "Lösche einen Benutzer" -#: Shell/UsersShell.php:78 +#: src/Shell/UsersShell.php:69 msgid "Reset the password via email" msgstr "Sende Passwort-Zurücksetzen E-Mail für eine E-Mail Adresse" -#: Shell/UsersShell.php:81 +#: src/Shell/UsersShell.php:72 msgid "Reset the password for all users" msgstr "Setze das Passwort für alle Benutzer" -#: Shell/UsersShell.php:84 +#: src/Shell/UsersShell.php:75 msgid "Reset the password for an specific user" msgstr "Setze das Passwort für einen Benutzer" -#: Shell/UsersShell.php:133;159 +#: src/Shell/UsersShell.php:135 src/Shell/UsersShell.php:161 msgid "Please enter a password." msgstr "Bitte geben Sie das Passwort ein." -#: Shell/UsersShell.php:137 +#: src/Shell/UsersShell.php:139 msgid "Password changed for all users" msgstr "Das Passwort wurde für alle Benutzer geändert" -#: Shell/UsersShell.php:138;166 +#: src/Shell/UsersShell.php:140 src/Shell/UsersShell.php:168 msgid "New password: {0}" msgstr "Neues Passwort: {0}" -#: Shell/UsersShell.php:156;184;262;359 +#: src/Shell/UsersShell.php:158 src/Shell/UsersShell.php:186 +#: src/Shell/UsersShell.php:214 src/Shell/UsersShell.php:304 +#: src/Shell/UsersShell.php:403 msgid "Please enter a username." msgstr "Bitte geben Sie einen Benutzernamen ein." -#: Shell/UsersShell.php:165 +#: src/Shell/UsersShell.php:167 msgid "Password changed for user: {0}" msgstr "Das Passwort wurde für den Benutzer: {0} geändert" -#: Shell/UsersShell.php:187 +#: src/Shell/UsersShell.php:189 msgid "Please enter a role." msgstr "Bitte geben Sie eine Rolle ein." -#: Shell/UsersShell.php:193 +#: src/Shell/UsersShell.php:195 msgid "Role changed for user: {0}" msgstr "Die Rolle wurde für den Benutzer: {0} geändert" -#: Shell/UsersShell.php:194 +#: src/Shell/UsersShell.php:196 msgid "New role: {0}" msgstr "Neue Rolle: {0}" -#: Shell/UsersShell.php:209 +#: src/Shell/UsersShell.php:217 +msgid "Please enter a token." +msgstr "Bitte geben Sie einen Token ein." + +#: src/Shell/UsersShell.php:224 +msgid "User was not saved, check validation errors" +msgstr "" +"Der Benutzer konnte nicht gespeichert werden. Bitte überprüfe die " +"Validierungsfehlermeldungen" + +#: src/Shell/UsersShell.php:229 +msgid "Api token changed for user: {0}" +msgstr "API Token für Benutzer: {0} wurde geändert" + +#: src/Shell/UsersShell.php:230 +msgid "New token: {0}" +msgstr "Neuer Token: {0}" + +#: src/Shell/UsersShell.php:245 msgid "User was activated: {0}" msgstr "Benutzer wurde aktiviert: {0}" -#: Shell/UsersShell.php:224 +#: src/Shell/UsersShell.php:260 msgid "User was de-activated: {0}" msgstr "Benutzer wurde deaktiviert: {0}" -#: Shell/UsersShell.php:236 +#: src/Shell/UsersShell.php:272 msgid "Please enter a username or email." msgstr "Bitte geben Sie einen Benutzername oder eine Email ein." -#: Shell/UsersShell.php:244 +#: src/Shell/UsersShell.php:280 msgid "" "Please ask the user to check the email to continue with password reset " "process" @@ -427,315 +497,330 @@ msgstr "" "Bitte Fragen Sie den Benutzer den Posteingang zu überprüfen für die weitere " "Vorgehensweise" -#: Shell/UsersShell.php:308 +#: src/Shell/UsersShell.php:350 msgid "Superuser added:" msgstr "Superuser hinzugefügt:" -#: Shell/UsersShell.php:310 +#: src/Shell/UsersShell.php:352 msgid "User added:" msgstr "Benutzer hinzugefügt:" -#: Shell/UsersShell.php:312 +#: src/Shell/UsersShell.php:354 msgid "Id: {0}" msgstr "ID: {0}" -#: Shell/UsersShell.php:313 +#: src/Shell/UsersShell.php:355 msgid "Username: {0}" msgstr "Benutzername: {0}" -#: Shell/UsersShell.php:314 +#: src/Shell/UsersShell.php:356 msgid "Email: {0}" msgstr "Email: {0}" -#: Shell/UsersShell.php:315 +#: src/Shell/UsersShell.php:357 msgid "Role: {0}" msgstr "Rolle: {0}" -#: Shell/UsersShell.php:316 +#: src/Shell/UsersShell.php:358 msgid "Password: {0}" msgstr "Passwort: {0}" -#: Shell/UsersShell.php:318 +#: src/Shell/UsersShell.php:360 msgid "User could not be added:" msgstr "Benutzer konnte nicht hinzugefügt werden:" -#: Shell/UsersShell.php:321 +#: src/Shell/UsersShell.php:363 msgid "Field: {0} Error: {1}" msgstr "Feld: {0} Fehler: {0}" -#: Shell/UsersShell.php:337 +#: src/Shell/UsersShell.php:379 msgid "The user was not found." msgstr "Der Benutzer konnte nicht gefunden werden." -#: Shell/UsersShell.php:367 +#: src/Shell/UsersShell.php:414 msgid "The user {0} was not deleted. Please try again" msgstr "" "Der Benutzer {0} konnte nicht gelöscht werden. Bitte versuchen Sie es erneut" -#: Shell/UsersShell.php:369 +#: src/Shell/UsersShell.php:416 msgid "The user {0} was deleted successfully" msgstr "Der Benutzer {0} wurde gelöscht" -#: 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 "Hallo {0}" - -#: Template/Email/html/reset_password.ctp:24 -msgid "Reset your password here" -msgstr "Passwort jetzt zurücksetzen" - -#: 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 "" -"Falls der Link nicht korrekt dargestellt wird kopieren Sie bitte die " -"folgende Adresse in ihren Web Browser {0}" +#: src/View/Helper/UserHelper.php:50 +msgid "Sign in with" +msgstr "Anmelden mit" -#: 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 "Vielen Dank" +#: src/View/Helper/UserHelper.php:113 +msgid "Logout" +msgstr "Abmelden" -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" -msgstr "Social Login aktivieren" +#: src/View/Helper/UserHelper.php:134 +msgid "Welcome, {0}" +msgstr "Willkommen, {0}" -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" -msgstr "Konto aktivieren" +#: src/View/Helper/UserHelper.php:165 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +msgstr "" +"reCaptcha ist nicht konfiguriert! Bitte setzten Sie Users.reCaptcha.key" -#: 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 "Bitte kopieren Sie die folgende Adresse in Ihren Web Browser {0}" +#: src/View/Helper/UserHelper.php:218 +msgid "Connected with {0}" +msgstr "Mit {0} verbunden" -#: 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 "" -"Bitte kopieren Sie die folgende Adresse in Ihren Web Browser um den Social " -"Login zu aktivieren {0}" +#: src/View/Helper/UserHelper.php:223 +msgid "Connect with {0}" +msgstr "Mit {0} verbinden" -#: Template/Users/add.ctp:13 Template/Users/edit.ctp:17 -#: Template/Users/index.ctp:13;26 Template/Users/view.ctp:15 +#: templates/Users/add.php:13 templates/Users/edit.php:17 +#: templates/Users/index.php:13 templates/Users/index.php:26 +#: templates/Users/view.php:15 msgid "Actions" msgstr "Aktionen" -#: Template/Users/add.ctp:15 Template/Users/edit.ctp:28 -#: Template/Users/view.ctp:23 +#: templates/Users/add.php:15 templates/Users/edit.php:28 +#: templates/Users/view.php:23 msgid "List Users" msgstr "Benutzer auflisten" -#: Template/Users/add.ctp:21 Template/Users/register.ctp:18 +#: templates/Users/add.php:21 templates/Users/register.php:18 msgid "Add User" msgstr "Benutzer hinzufügen" -#: Template/Users/add.ctp:23 Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:22 Template/Users/login.ctp:20 -#: Template/Users/profile.ctp:30 Template/Users/register.ctp:20 -#: Template/Users/view.ctp:33 +#: templates/Users/add.php:23 templates/Users/edit.php:36 +#: templates/Users/index.php:22 templates/Users/login.php:20 +#: templates/Users/profile.php:30 templates/Users/register.php:20 +#: templates/Users/view.php:33 msgid "Username" msgstr "Benutzername" -#: Template/Users/add.ctp:24 Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:23 Template/Users/profile.ctp:32 -#: Template/Users/register.ctp:21 Template/Users/view.ctp:35 +#: templates/Users/add.php:24 templates/Users/edit.php:37 +#: templates/Users/index.php:23 templates/Users/profile.php:32 +#: templates/Users/register.php:21 templates/Users/view.php:35 msgid "Email" msgstr "Email" -#: Template/Users/add.ctp:25 Template/Users/login.ctp:21 -#: Template/Users/register.ctp:22 +#: templates/Users/add.php:25 templates/Users/login.php:21 +#: templates/Users/register.php:22 msgid "Password" msgstr "Passwort" -#: Template/Users/add.ctp:26 Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:24 Template/Users/register.ctp:27 +#: templates/Users/add.php:26 templates/Users/edit.php:38 +#: templates/Users/index.php:24 templates/Users/register.php:28 msgid "First name" msgstr "Vorname" -#: Template/Users/add.ctp:27 Template/Users/edit.ctp:39 -#: Template/Users/index.ctp:25 Template/Users/register.ctp:28 +#: templates/Users/add.php:27 templates/Users/edit.php:39 +#: templates/Users/index.php:25 templates/Users/register.php:29 msgid "Last name" msgstr "Nachname" -#: Template/Users/add.ctp:30 Template/Users/edit.ctp:54 -#: Template/Users/view.ctp:49;74 +#: templates/Users/add.php:30 templates/Users/edit.php:54 +#: templates/Users/view.php:49 templates/Users/view.php:74 msgid "Active" msgstr "Aktiv" -#: Template/Users/add.ctp:34 Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:58 Template/Users/register.ctp:37 -#: Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:19 +#: templates/Users/add.php:34 templates/Users/change_password.php:25 +#: templates/Users/edit.php:58 templates/Users/register.php:38 +#: templates/Users/request_reset_password.php:23 +#: templates/Users/resend_token_validation.php:20 +#: templates/Users/social_email.php:19 msgid "Submit" msgstr "Absenden" -#: Template/Users/change_password.ctp:5 +#: templates/Users/change_password.php:5 msgid "Please enter the new password" msgstr "Bitte geben Sie ihr neues Passwort ein" -#: Template/Users/change_password.ctp:10 +#: templates/Users/change_password.php:10 msgid "Current password" msgstr "Aktuelles Passwort" -#: Template/Users/change_password.ctp:16 +#: templates/Users/change_password.php:16 msgid "New password" msgstr "Neues Passwort" -#: Template/Users/change_password.ctp:21 Template/Users/register.ctp:25 +#: templates/Users/change_password.php:21 templates/Users/register.php:26 msgid "Confirm password" msgstr "Neues Passwort bestätigen" -#: Template/Users/edit.ctp:22 Template/Users/index.ctp:40 +#: templates/Users/edit.php:22 templates/Users/index.php:40 msgid "Delete" msgstr "Löschen" -#: Template/Users/edit.ctp:24 Template/Users/index.ctp:40 -#: Template/Users/view.ctp:21 +#: templates/Users/edit.php:24 templates/Users/index.php:40 +#: templates/Users/view.php:21 msgid "Are you sure you want to delete # {0}?" msgstr "Sind Sie sicher, dass Sie # {0} löschen wollen?" -#: Template/Users/edit.ctp:34 Template/Users/view.ctp:17 +#: templates/Users/edit.php:34 templates/Users/view.php:17 msgid "Edit User" msgstr "Benutzer bearbeiten" -#: Template/Users/edit.ctp:40 Template/Users/view.ctp:43 +#: templates/Users/edit.php:40 templates/Users/view.php:43 msgid "Token" msgstr "Token" -#: Template/Users/edit.ctp:42 +#: templates/Users/edit.php:42 msgid "Token expires" msgstr "Token Ablaufdatum" -#: Template/Users/edit.ctp:45 +#: templates/Users/edit.php:45 msgid "API token" msgstr "API Token" -#: Template/Users/edit.ctp:48 +#: templates/Users/edit.php:48 msgid "Activation date" msgstr "Aktivierungsdatum" -#: Template/Users/edit.ctp:51 +#: templates/Users/edit.php:51 msgid "TOS date" msgstr "AGB Datum" -#: Template/Users/edit.ctp:64 +#: templates/Users/edit.php:64 msgid "Reset Google Authenticator Token" msgstr "Google Authenticator Token zurücksetzen" -#: Template/Users/edit.ctp:70 +#: templates/Users/edit.php:70 msgid "Are you sure you want to reset token for user \"{0}\"?" msgstr "" "Sind Sie sicher, dass Sie den Token für den Benutzer # {0} zurücksetzen " "wollen?" -#: Template/Users/index.ctp:15 +#: templates/Users/index.php:15 msgid "New {0}" msgstr "Neuer {0}" -#: Template/Users/index.ctp:37 +#: templates/Users/index.php:37 msgid "View" msgstr "Ansicht" -#: Template/Users/index.ctp:38 +#: templates/Users/index.php:38 msgid "Change password" msgstr "Passwort ändern" -#: Template/Users/index.ctp:39 +#: templates/Users/index.php:39 msgid "Edit" msgstr "Bearbeiten" -#: Template/Users/index.ctp:49 +#: templates/Users/index.php:49 msgid "previous" msgstr "vorherig" -#: Template/Users/index.ctp:51 +#: templates/Users/index.php:51 msgid "next" msgstr "nächste" -#: Template/Users/login.ctp:19 +#: templates/Users/login.php:19 msgid "Please enter your username and password" msgstr "Bitte geben Sie ihren Benutzernamen und Passwort ein" -#: Template/Users/login.ctp:29 +#: templates/Users/login.php:29 msgid "Remember me" msgstr "Angemeldet bleiben" -#: Template/Users/login.ctp:37 +#: templates/Users/login.php:37 msgid "Register" msgstr "Registrieren" -#: Template/Users/login.ctp:43 +#: templates/Users/login.php:43 msgid "Reset Password" msgstr "Passwort zurücksetzen" -#: Template/Users/login.ctp:48 +#: templates/Users/login.php:48 msgid "Login" msgstr "Anmelden" -#: Template/Users/profile.ctp:21 +#: templates/Users/profile.php:21 msgid "{0} {1}" msgstr "{0} {1}" -#: Template/Users/profile.ctp:27 +#: templates/Users/profile.php:27 msgid "Change Password" msgstr "Passwort ändern" -#: Template/Users/profile.ctp:38 Template/Users/view.ctp:68 +#: templates/Users/profile.php:38 templates/Users/view.php:68 msgid "Social Accounts" msgstr "Social Accounts" -#: Template/Users/profile.ctp:42 Template/Users/view.ctp:73 +#: templates/Users/profile.php:42 templates/Users/view.php:73 msgid "Avatar" msgstr "Avatar" -#: Template/Users/profile.ctp:43 Template/Users/view.ctp:72 +#: templates/Users/profile.php:43 templates/Users/view.php:72 msgid "Provider" msgstr "Provider" -#: Template/Users/profile.ctp:44 +#: templates/Users/profile.php:44 msgid "Link" msgstr "Link" -#: Template/Users/profile.ctp:51 +#: templates/Users/profile.php:51 msgid "Link to {0}" msgstr "Link zu {0}" -#: Template/Users/register.ctp:30 +#: templates/Users/register.php:31 msgid "Accept TOS conditions?" msgstr "AGBs akzeptieren?" -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" -msgstr "Bitte geben Sie ihre Email Adresse ein um ihr Passwort zurückzusetzen" +#: templates/Users/request_reset_password.php:20 +msgid "Please enter your email or username to reset your password" +msgstr "" +"Bitte geben Sie ihre Email Adresse oder Benutzernamen ein um ihr Passwort " +"zurückzusetzen" -#: Template/Users/resend_token_validation.ctp:15 +#: templates/Users/resend_token_validation.php:15 msgid "Resend Validation email" msgstr "Validierungs-Email erneut versenden" -#: Template/Users/resend_token_validation.ctp:17 +#: templates/Users/resend_token_validation.php:17 msgid "Email or username" msgstr "Email oder Benutzername" -#: Template/Users/verify.ctp:13 +#: templates/Users/u2f_authenticate.php:22 templates/Users/webauthn2fa.php:25 +msgid "Verify your registered yubico key" +msgstr "Bestätige deinen registrierten Yubico Key" + +#: templates/Users/u2f_authenticate.php:23 templates/Users/u2f_register.php:23 +#: templates/Users/webauthn2fa.php:20 templates/Users/webauthn2fa.php:26 +msgid "Please insert and tap your yubico key" +msgstr "Bitte Yubico Key anstecken und antippen" + +#: templates/Users/u2f_authenticate.php:24 templates/Users/webauthn2fa.php:27 +msgid "" +"You can now finish the authentication process using the registered device." +msgstr "" +"Sie können nun den Authentifizierungs-Prozess mit dem registrierten Gerät " +"fertigstellen." + +#: templates/Users/u2f_authenticate.php:25 templates/Users/webauthn2fa.php:22 +#: templates/Users/webauthn2fa.php:28 +msgid "" +"When the YubiKey starts blinking, press the golden disc to activate it. " +"Depending on the web browser you might need to confirm the use of extended " +"information from the YubiKey." +msgstr "" +"Wenn der YubiKey anfängt zu blinken drücken Sie bitte die goldene Diskette " +"um ihn zu aktivieren. Abhängig vom Web-Browser könnten Berechtigungs-Popups " +"erscheinen um den YubiKey zu verwenden." + +#: templates/Users/u2f_authenticate.php:27 templates/Users/u2f_register.php:27 +#: templates/Users/webauthn2fa.php:31 +msgid "Reload" +msgstr "Neu laden" + +#: templates/Users/u2f_authenticate.php:51 templates/Users/u2f_register.php:56 +msgid "Yubico key check has failed, please try again" +msgstr "Yubico Key Überprüfung fehlgeschlagen. Bitte versuchen Sie es erneut" + +#: templates/Users/u2f_register.php:22 templates/Users/webauthn2fa.php:19 +msgid "Registering your yubico key" +msgstr "Yubico Key registrieren" + +#: templates/Users/verify.php:13 msgid "Verification Code" msgstr "Bestätigungscode" -#: Template/Users/verify.ctp:15 +#: templates/Users/verify.php:15 msgid "" " " "Verify" @@ -743,75 +828,114 @@ msgstr "" " " "Bestätigen" -#: Template/Users/view.ctp:19 +#: templates/Users/view.php:19 msgid "Delete User" msgstr "Benutzer löschen" -#: Template/Users/view.ctp:24 +#: templates/Users/view.php:24 msgid "New User" msgstr "Benutzer hinzufügen" -#: Template/Users/view.ctp:31 +#: templates/Users/view.php:31 msgid "Id" msgstr "ID" -#: Template/Users/view.ctp:37 +#: templates/Users/view.php:37 msgid "First Name" msgstr "Vorname" -#: Template/Users/view.ctp:39 +#: templates/Users/view.php:39 msgid "Last Name" msgstr "Nachname" -#: Template/Users/view.ctp:41 +#: templates/Users/view.php:41 msgid "Role" msgstr "Rolle" -#: Template/Users/view.ctp:45 +#: templates/Users/view.php:45 msgid "Api Token" msgstr "API Token" -#: Template/Users/view.ctp:53 +#: templates/Users/view.php:53 msgid "Token Expires" msgstr "Token Ablaufdatum" -#: Template/Users/view.ctp:55 +#: templates/Users/view.php:55 msgid "Activation Date" msgstr "Aktivierungsdatum" -#: Template/Users/view.ctp:57 +#: templates/Users/view.php:57 msgid "Tos Date" msgstr "AGB Datum" -#: Template/Users/view.ctp:59;75 +#: templates/Users/view.php:59 templates/Users/view.php:75 msgid "Created" msgstr "erstellt am" -#: Template/Users/view.ctp:61;76 +#: templates/Users/view.php:61 templates/Users/view.php:76 msgid "Modified" msgstr "zuletzt aktualisiert" -#: View/Helper/UserHelper.php:46 -msgid "Sign in with" -msgstr "Anmelden mit" +#: templates/Users/webauthn2fa.php:8 +msgid "Two-factor authentication" +msgstr "Two-Factor Authentifizierung" -#: View/Helper/UserHelper.php:103 -msgid "Logout" -msgstr "Abmelden" +#: templates/Users/webauthn2fa.php:21 +msgid "" +"In order to enable your YubiKey the first step is to perform a registration." +msgstr "" +"Damit Sie ihren YubiKey verwenden können müssen Sie diesen zuerst " +"registrieren." + +#: templates/email/html/reset_password.php:14 +#: templates/email/html/social_account_validation.php:14 +#: templates/email/html/validation.php:13 +#: templates/email/text/reset_password.php:12 +#: templates/email/text/social_account_validation.php:12 +#: templates/email/text/validation.php:12 +msgid "Hi {0}" +msgstr "Hallo {0}" -#: View/Helper/UserHelper.php:121 -msgid "Welcome, {0}" -msgstr "Willkommen, {0}" +#: templates/email/html/reset_password.php:17 +msgid "Reset your password here" +msgstr "Passwort jetzt zurücksetzen" -#: View/Helper/UserHelper.php:151 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +#: templates/email/html/reset_password.php:20 +#: templates/email/html/social_account_validation.php:23 +#: templates/email/html/validation.php:19 +msgid "" +"If the link is not correctly displayed, please copy the following address in " +"your web browser {0}" msgstr "" -"reCaptcha ist nicht konfiguriert! Bitte setzten Sie Users.reCaptcha.key" +"Falls der Link nicht korrekt dargestellt wird kopieren Sie bitte die " +"folgende Adresse in ihren Web Browser {0}" -#: View/Helper/UserHelper.php:215 -msgid "Connected with {0}" -msgstr "Mit {0} verbunden" +#: templates/email/html/reset_password.php:27 +#: templates/email/html/social_account_validation.php:30 +#: templates/email/html/validation.php:26 +#: templates/email/text/reset_password.php:20 +#: templates/email/text/social_account_validation.php:20 +#: templates/email/text/validation.php:20 +msgid "Thank you" +msgstr "Vielen Dank" -#: View/Helper/UserHelper.php:220 -msgid "Connect with {0}" -msgstr "Mit {0} verbinden" +#: templates/email/html/social_account_validation.php:18 +msgid "Activate your social login here" +msgstr "Social Login aktivieren" + +#: templates/email/html/validation.php:16 +msgid "Activate your account here" +msgstr "Konto aktivieren" + +#: templates/email/text/reset_password.php:14 +#: templates/email/text/validation.php:14 +msgid "Please copy the following address in your web browser {0}" +msgstr "Bitte kopieren Sie die folgende Adresse in Ihren Web Browser {0}" + +#: templates/email/text/social_account_validation.php:14 +msgid "" +"Please copy the following address in your web browser to activate your " +"social login {0}" +msgstr "" +"Bitte kopieren Sie die folgende Adresse in Ihren Web Browser um den Social " +"Login zu aktivieren {0}" diff --git a/resources/locales/users.pot b/resources/locales/users.pot index 59f36b747..c2992ab07 100644 --- a/resources/locales/users.pot +++ b/resources/locales/users.pot @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" -"POT-Creation-Date: 2019-01-10 14:38+0000\n" +"POT-Creation-Date: 2022-03-11 13:46+0100\n" "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" "Last-Translator: NAME \n" "Language-Team: LANGUAGE \n" @@ -14,789 +14,907 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#: Controller/SocialAccountsController.php:50 +#: src/Controller/SocialAccountsController.php:50 msgid "Account validated successfully" msgstr "" -#: Controller/SocialAccountsController.php:52 +#: src/Controller/SocialAccountsController.php:52 msgid "Account could not be validated" msgstr "" -#: Controller/SocialAccountsController.php:55 +#: src/Controller/SocialAccountsController.php:55 msgid "Invalid token and/or social account" msgstr "" -#: Controller/SocialAccountsController.php:57;85 +#: src/Controller/SocialAccountsController.php:57 +#: src/Controller/SocialAccountsController.php:85 msgid "Social Account already active" msgstr "" -#: Controller/SocialAccountsController.php:59 +#: src/Controller/SocialAccountsController.php:59 msgid "Social Account could not be validated" msgstr "" -#: Controller/SocialAccountsController.php:78 +#: src/Controller/SocialAccountsController.php:78 msgid "Email sent successfully" msgstr "" -#: Controller/SocialAccountsController.php:80 +#: src/Controller/SocialAccountsController.php:80 msgid "Email could not be sent" msgstr "" -#: Controller/SocialAccountsController.php:83 +#: src/Controller/SocialAccountsController.php:83 msgid "Invalid account" msgstr "" -#: Controller/SocialAccountsController.php:87 +#: src/Controller/SocialAccountsController.php:87 msgid "Email could not be resent" msgstr "" -#: Controller/Traits/LinkSocialTrait.php:52 +#: src/Controller/Traits/LinkSocialTrait.php:56 msgid "Could not associate account, please try again." msgstr "" -#: Controller/Traits/LinkSocialTrait.php:76 +#: src/Controller/Traits/LinkSocialTrait.php:80 msgid "Social account was associated." msgstr "" -#: Controller/Traits/LoginTrait.php:73 +#: src/Controller/Traits/LoginTrait.php:73 msgid "You've successfully logged out" msgstr "" -#: Controller/Traits/OneTimePasswordVerifyTrait.php:71 +#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:75 msgid "Please enable Google Authenticator first." msgstr "" -#: Controller/Traits/OneTimePasswordVerifyTrait.php:80 +#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:90 msgid "Could not find user data" msgstr "" -#: Controller/Traits/OneTimePasswordVerifyTrait.php:116 +#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:129 msgid "Could not verify, please try again" msgstr "" -#: Controller/Traits/OneTimePasswordVerifyTrait.php:144 +#: src/Controller/Traits/OneTimePasswordVerifyTrait.php:161 msgid "Verification code is invalid. Try again" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:53;91 -#: Controller/Traits/ProfileTrait.php:53 +#: src/Controller/Traits/PasswordManagementTrait.php:63 +msgid "Changing another user's password is not allowed" +msgstr "" + +#: src/Controller/Traits/PasswordManagementTrait.php:77 +#: src/Controller/Traits/PasswordManagementTrait.php:121 +#: src/Controller/Traits/ProfileTrait.php:54 msgid "User was not found" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:75;87;95 +#: src/Controller/Traits/PasswordManagementTrait.php:105 +#: src/Controller/Traits/PasswordManagementTrait.php:117 +#: src/Controller/Traits/PasswordManagementTrait.php:125 msgid "Password could not be changed" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:83 +#: src/Controller/Traits/PasswordManagementTrait.php:113 msgid "Password has been changed successfully" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:137 +#: src/Controller/Traits/PasswordManagementTrait.php:167 msgid "Please check your email to continue with password reset process" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:140 -#: Shell/UsersShell.php:247 +#: src/Controller/Traits/PasswordManagementTrait.php:170 +#: src/Shell/UsersShell.php:286 msgid "The password token could not be generated. Please try again" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:146 -#: Controller/Traits/UserValidationTrait.php:116 +#: src/Controller/Traits/PasswordManagementTrait.php:176 +#: src/Controller/Traits/UserValidationTrait.php:124 msgid "User {0} was not found" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:148 +#: src/Controller/Traits/PasswordManagementTrait.php:178 msgid "The user is not active" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:150 -#: Controller/Traits/UserValidationTrait.php:111;120 +#: src/Controller/Traits/PasswordManagementTrait.php:180 +#: src/Controller/Traits/UserValidationTrait.php:119 +#: src/Controller/Traits/UserValidationTrait.php:128 msgid "Token could not be reset" msgstr "" -#: Controller/Traits/PasswordManagementTrait.php:174 +#: src/Controller/Traits/PasswordManagementTrait.php:204 msgid "Google Authenticator token was successfully reset" msgstr "" -#: Controller/Traits/ProfileTrait.php:57 +#: src/Controller/Traits/PasswordManagementTrait.php:207 +msgid "Could not reset Google Authenticator" +msgstr "" + +#: src/Controller/Traits/ProfileTrait.php:58 msgid "Not authorized, please login first" msgstr "" -#: Controller/Traits/RegisterTrait.php:46 +#: src/Controller/Traits/RegisterTrait.php:47 msgid "You must log out to register a new user account" msgstr "" -#: Controller/Traits/RegisterTrait.php:75;99 +#: src/Controller/Traits/RegisterTrait.php:86 +#: src/Controller/Traits/RegisterTrait.php:117 msgid "The user could not be saved" msgstr "" -#: Controller/Traits/RegisterTrait.php:92 -#: Loader/LoginComponentLoader.php:32 +#: src/Controller/Traits/RegisterTrait.php:103 +#: src/Loader/LoginComponentLoader.php:33 msgid "Invalid reCaptcha" msgstr "" -#: Controller/Traits/RegisterTrait.php:133 +#: src/Controller/Traits/RegisterTrait.php:151 msgid "You have registered successfully, please log in" msgstr "" -#: Controller/Traits/RegisterTrait.php:135 +#: src/Controller/Traits/RegisterTrait.php:153 msgid "Please validate your account before log in" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:77;107 +#: src/Controller/Traits/SimpleCrudTrait.php:77 +#: src/Controller/Traits/SimpleCrudTrait.php:107 msgid "The {0} has been saved" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:81;111 +#: src/Controller/Traits/SimpleCrudTrait.php:81 +#: src/Controller/Traits/SimpleCrudTrait.php:111 msgid "The {0} could not be saved" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:131 +#: src/Controller/Traits/SimpleCrudTrait.php:131 msgid "The {0} has been deleted" msgstr "" -#: Controller/Traits/SimpleCrudTrait.php:133 +#: src/Controller/Traits/SimpleCrudTrait.php:133 msgid "The {0} could not be deleted" msgstr "" -#: Controller/Traits/UserValidationTrait.php:44 +#: src/Controller/Traits/U2fTrait.php:216 +msgid "U2F requires SSL." +msgstr "" + +#: src/Controller/Traits/UserValidationTrait.php:49 msgid "User account validated successfully" msgstr "" -#: Controller/Traits/UserValidationTrait.php:46 +#: src/Controller/Traits/UserValidationTrait.php:51 msgid "User account could not be validated" msgstr "" -#: Controller/Traits/UserValidationTrait.php:49 +#: src/Controller/Traits/UserValidationTrait.php:54 msgid "User already active" msgstr "" -#: Controller/Traits/UserValidationTrait.php:55 +#: src/Controller/Traits/UserValidationTrait.php:60 msgid "Reset password token was validated successfully" msgstr "" -#: Controller/Traits/UserValidationTrait.php:63 +#: src/Controller/Traits/UserValidationTrait.php:68 msgid "Reset password token could not be validated" msgstr "" -#: Controller/Traits/UserValidationTrait.php:67 +#: src/Controller/Traits/UserValidationTrait.php:72 msgid "Invalid validation type" msgstr "" -#: Controller/Traits/UserValidationTrait.php:70 +#: src/Controller/Traits/UserValidationTrait.php:75 msgid "Invalid token or user account already validated" msgstr "" -#: Controller/Traits/UserValidationTrait.php:76 +#: src/Controller/Traits/UserValidationTrait.php:81 msgid "Token already expired" msgstr "" -#: Controller/Traits/UserValidationTrait.php:106 +#: src/Controller/Traits/UserValidationTrait.php:114 msgid "Token has been reset successfully. Please check your email." msgstr "" -#: Controller/Traits/UserValidationTrait.php:118 +#: src/Controller/Traits/UserValidationTrait.php:126 msgid "User {0} is already active" msgstr "" -#: Loader/LoginComponentLoader.php:30 +#: src/Controller/Traits/Webauthn2faTrait.php:53 +#: src/Controller/Traits/Webauthn2faTrait.php:73 +msgid "User already has configured webauthn2fa" +msgstr "" + +#: src/Controller/Traits/Webauthn2faTrait.php:77 +#: src/Controller/Traits/Webauthn2faTrait.php:122 +msgid "Register error with webauthn for user id: {0}" +msgstr "" + +#: src/Loader/AuthenticationServiceLoader.php:109 +msgid "Property {0}.className should be defined" +msgstr "" + +#: src/Loader/LoginComponentLoader.php:31 msgid "Username or password is incorrect" msgstr "" -#: Loader/LoginComponentLoader.php:51 +#: src/Loader/LoginComponentLoader.php:52 msgid "Could not proceed with social account. Please try again" msgstr "" -#: Loader/LoginComponentLoader.php:53 +#: src/Loader/LoginComponentLoader.php:54 msgid "Your user has not been validated yet. Please check your inbox for instructions" msgstr "" -#: Loader/LoginComponentLoader.php:57 +#: src/Loader/LoginComponentLoader.php:58 msgid "Your social account has not been validated yet. Please check your inbox for instructions" msgstr "" -#: Mailer/UsersMailer.php:33 +#: src/Mailer/UsersMailer.php:36 msgid "Your account validation link" msgstr "" -#: Mailer/UsersMailer.php:51 +#: src/Mailer/UsersMailer.php:63 msgid "{0}Your reset password link" msgstr "" -#: Mailer/UsersMailer.php:74 +#: src/Mailer/UsersMailer.php:95 msgid "{0}Your social account validation link" msgstr "" -#: Middleware/SocialAuthMiddleware.php:65 -#: Template/Users/social_email.ctp:16 +#: src/Middleware/SocialAuthMiddleware.php:47 +#: templates/Users/social_email.php:16 msgid "Please enter your email" msgstr "" -#: Middleware/SocialAuthMiddleware.php:75 +#: src/Middleware/SocialAuthMiddleware.php:57 msgid "Could not identify your account, please try again" msgstr "" -#: Model/Behavior/AuthFinderBehavior.php:48 +#: src/Middleware/UnauthorizedHandler/DefaultRedirectHandler.php:112 +msgid "You are not authorized to access that location." +msgstr "" + +#: src/Model/Behavior/AuthFinderBehavior.php:49 msgid "Missing 'username' in options data" msgstr "" -#: Model/Behavior/LinkSocialBehavior.php:53 +#: src/Model/Behavior/LinkSocialBehavior.php:52 msgid "Social account already associated to another user" msgstr "" -#: Model/Behavior/PasswordBehavior.php:45 +#: src/Model/Behavior/PasswordBehavior.php:45 msgid "Reference cannot be null" msgstr "" -#: Model/Behavior/PasswordBehavior.php:50 +#: src/Model/Behavior/PasswordBehavior.php:50 msgid "Token expiration cannot be empty" msgstr "" -#: Model/Behavior/PasswordBehavior.php:56;138 +#: src/Model/Behavior/PasswordBehavior.php:56 +#: src/Model/Behavior/PasswordBehavior.php:136 msgid "User not found" msgstr "" -#: Model/Behavior/PasswordBehavior.php:60 -#: Model/Behavior/RegisterBehavior.php:112 +#: src/Model/Behavior/PasswordBehavior.php:60 +#: src/Model/Behavior/RegisterBehavior.php:129 msgid "User account already validated" msgstr "" -#: Model/Behavior/PasswordBehavior.php:67 +#: src/Model/Behavior/PasswordBehavior.php:66 msgid "User not active" msgstr "" -#: Model/Behavior/PasswordBehavior.php:143 +#: src/Model/Behavior/PasswordBehavior.php:141 msgid "The current password does not match" msgstr "" -#: Model/Behavior/PasswordBehavior.php:146 +#: src/Model/Behavior/PasswordBehavior.php:144 msgid "You cannot use the current password as the new one" msgstr "" -#: Model/Behavior/RegisterBehavior.php:90 +#: src/Model/Behavior/RegisterBehavior.php:107 msgid "User not found for the given token and email." msgstr "" -#: Model/Behavior/RegisterBehavior.php:93 +#: src/Model/Behavior/RegisterBehavior.php:110 msgid "Token has already expired user with no token" msgstr "" -#: Model/Behavior/RegisterBehavior.php:151 +#: src/Model/Behavior/RegisterBehavior.php:167 msgid "This field is required" msgstr "" -#: Model/Behavior/SocialAccountBehavior.php:102;129 +#: src/Model/Behavior/SocialAccountBehavior.php:100 +#: src/Model/Behavior/SocialAccountBehavior.php:130 msgid "Account already validated" msgstr "" -#: Model/Behavior/SocialAccountBehavior.php:105;132 +#: src/Model/Behavior/SocialAccountBehavior.php:104 +#: src/Model/Behavior/SocialAccountBehavior.php:135 msgid "Account not found for the given token and email." msgstr "" -#: Model/Behavior/SocialBehavior.php:83 +#: src/Model/Behavior/SocialBehavior.php:85 msgid "Unable to login user with reference {0}" msgstr "" -#: Model/Behavior/SocialBehavior.php:122 +#: src/Model/Behavior/SocialBehavior.php:136 msgid "Email not present" msgstr "" -#: Model/Table/UsersTable.php:79 +#: src/Model/Table/UsersTable.php:107 msgid "Your password does not match your confirm password. Please try again" msgstr "" -#: Model/Table/UsersTable.php:171 +#: src/Model/Table/UsersTable.php:201 msgid "Username already exists" msgstr "" -#: Model/Table/UsersTable.php:177 +#: src/Model/Table/UsersTable.php:207 msgid "Email already exists" msgstr "" -#: Shell/UsersShell.php:58 +#: src/Shell/UsersShell.php:46 msgid "Utilities for CakeDC Users Plugin" msgstr "" -#: Shell/UsersShell.php:60 +#: src/Shell/UsersShell.php:48 msgid "Activate an specific user" msgstr "" -#: Shell/UsersShell.php:63 +#: src/Shell/UsersShell.php:51 msgid "Add a new superadmin user for testing purposes" msgstr "" -#: Shell/UsersShell.php:66 +#: src/Shell/UsersShell.php:54 msgid "Add a new user" msgstr "" -#: Shell/UsersShell.php:69 +#: src/Shell/UsersShell.php:57 msgid "Change the role for an specific user" msgstr "" -#: Shell/UsersShell.php:72 +#: src/Shell/UsersShell.php:60 +msgid "Change the api token for an specific user" +msgstr "" + +#: src/Shell/UsersShell.php:63 msgid "Deactivate an specific user" msgstr "" -#: Shell/UsersShell.php:75 +#: src/Shell/UsersShell.php:66 msgid "Delete an specific user" msgstr "" -#: Shell/UsersShell.php:78 +#: src/Shell/UsersShell.php:69 msgid "Reset the password via email" msgstr "" -#: Shell/UsersShell.php:81 +#: src/Shell/UsersShell.php:72 msgid "Reset the password for all users" msgstr "" -#: Shell/UsersShell.php:84 +#: src/Shell/UsersShell.php:75 msgid "Reset the password for an specific user" msgstr "" -#: Shell/UsersShell.php:133;159 +#: src/Shell/UsersShell.php:135 +#: src/Shell/UsersShell.php:161 msgid "Please enter a password." msgstr "" -#: Shell/UsersShell.php:137 +#: src/Shell/UsersShell.php:139 msgid "Password changed for all users" msgstr "" -#: Shell/UsersShell.php:138;166 +#: src/Shell/UsersShell.php:140 +#: src/Shell/UsersShell.php:168 msgid "New password: {0}" msgstr "" -#: Shell/UsersShell.php:156;184;262;359 +#: src/Shell/UsersShell.php:158 +#: src/Shell/UsersShell.php:186 +#: src/Shell/UsersShell.php:214 +#: src/Shell/UsersShell.php:304 +#: src/Shell/UsersShell.php:403 msgid "Please enter a username." msgstr "" -#: Shell/UsersShell.php:165 +#: src/Shell/UsersShell.php:167 msgid "Password changed for user: {0}" msgstr "" -#: Shell/UsersShell.php:187 +#: src/Shell/UsersShell.php:189 msgid "Please enter a role." msgstr "" -#: Shell/UsersShell.php:193 +#: src/Shell/UsersShell.php:195 msgid "Role changed for user: {0}" msgstr "" -#: Shell/UsersShell.php:194 +#: src/Shell/UsersShell.php:196 msgid "New role: {0}" msgstr "" -#: Shell/UsersShell.php:209 +#: src/Shell/UsersShell.php:217 +msgid "Please enter a token." +msgstr "" + +#: src/Shell/UsersShell.php:224 +msgid "User was not saved, check validation errors" +msgstr "" + +#: src/Shell/UsersShell.php:229 +msgid "Api token changed for user: {0}" +msgstr "" + +#: src/Shell/UsersShell.php:230 +msgid "New token: {0}" +msgstr "" + +#: src/Shell/UsersShell.php:245 msgid "User was activated: {0}" msgstr "" -#: Shell/UsersShell.php:224 +#: src/Shell/UsersShell.php:260 msgid "User was de-activated: {0}" msgstr "" -#: Shell/UsersShell.php:236 +#: src/Shell/UsersShell.php:272 msgid "Please enter a username or email." msgstr "" -#: Shell/UsersShell.php:244 +#: src/Shell/UsersShell.php:280 msgid "Please ask the user to check the email to continue with password reset process" msgstr "" -#: Shell/UsersShell.php:308 +#: src/Shell/UsersShell.php:350 msgid "Superuser added:" msgstr "" -#: Shell/UsersShell.php:310 +#: src/Shell/UsersShell.php:352 msgid "User added:" msgstr "" -#: Shell/UsersShell.php:312 +#: src/Shell/UsersShell.php:354 msgid "Id: {0}" msgstr "" -#: Shell/UsersShell.php:313 +#: src/Shell/UsersShell.php:355 msgid "Username: {0}" msgstr "" -#: Shell/UsersShell.php:314 +#: src/Shell/UsersShell.php:356 msgid "Email: {0}" msgstr "" -#: Shell/UsersShell.php:315 +#: src/Shell/UsersShell.php:357 msgid "Role: {0}" msgstr "" -#: Shell/UsersShell.php:316 +#: src/Shell/UsersShell.php:358 msgid "Password: {0}" msgstr "" -#: Shell/UsersShell.php:318 +#: src/Shell/UsersShell.php:360 msgid "User could not be added:" msgstr "" -#: Shell/UsersShell.php:321 +#: src/Shell/UsersShell.php:363 msgid "Field: {0} Error: {1}" msgstr "" -#: Shell/UsersShell.php:337 +#: src/Shell/UsersShell.php:379 msgid "The user was not found." msgstr "" -#: Shell/UsersShell.php:367 +#: src/Shell/UsersShell.php:414 msgid "The user {0} was not deleted. Please try again" msgstr "" -#: Shell/UsersShell.php:369 +#: src/Shell/UsersShell.php:416 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}" +#: src/View/Helper/UserHelper.php:50 +msgid "Sign in with" 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" +#: src/View/Helper/UserHelper.php:113 +msgid "Logout" msgstr "" -#: Template/Email/html/social_account_validation.ctp:18 -msgid "Activate your social login here" +#: src/View/Helper/UserHelper.php:134 +msgid "Welcome, {0}" msgstr "" -#: Template/Email/html/validation.ctp:24 -msgid "Activate your account here" +#: src/View/Helper/UserHelper.php:165 +msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" 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}" +#: src/View/Helper/UserHelper.php:218 +msgid "Connected with {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}" +#: src/View/Helper/UserHelper.php:223 +msgid "Connect with {0}" msgstr "" -#: Template/Users/add.ctp:13 -#: Template/Users/edit.ctp:17 -#: Template/Users/index.ctp:13;26 -#: Template/Users/view.ctp:15 +#: templates/Users/add.php:13 +#: templates/Users/edit.php:17 +#: templates/Users/index.php:13 +#: templates/Users/index.php:26 +#: templates/Users/view.php:15 msgid "Actions" msgstr "" -#: Template/Users/add.ctp:15 -#: Template/Users/edit.ctp:28 -#: Template/Users/view.ctp:23 +#: templates/Users/add.php:15 +#: templates/Users/edit.php:28 +#: templates/Users/view.php:23 msgid "List Users" msgstr "" -#: Template/Users/add.ctp:21 -#: Template/Users/register.ctp:18 +#: templates/Users/add.php:21 +#: templates/Users/register.php:18 msgid "Add User" msgstr "" -#: Template/Users/add.ctp:23 -#: Template/Users/edit.ctp:36 -#: Template/Users/index.ctp:22 -#: Template/Users/login.ctp:20 -#: Template/Users/profile.ctp:30 -#: Template/Users/register.ctp:20 -#: Template/Users/view.ctp:33 +#: templates/Users/add.php:23 +#: templates/Users/edit.php:36 +#: templates/Users/index.php:22 +#: templates/Users/login.php:20 +#: templates/Users/profile.php:30 +#: templates/Users/register.php:20 +#: templates/Users/view.php:33 msgid "Username" msgstr "" -#: Template/Users/add.ctp:24 -#: Template/Users/edit.ctp:37 -#: Template/Users/index.ctp:23 -#: Template/Users/profile.ctp:32 -#: Template/Users/register.ctp:21 -#: Template/Users/view.ctp:35 +#: templates/Users/add.php:24 +#: templates/Users/edit.php:37 +#: templates/Users/index.php:23 +#: templates/Users/profile.php:32 +#: templates/Users/register.php:21 +#: templates/Users/view.php:35 msgid "Email" msgstr "" -#: Template/Users/add.ctp:25 -#: Template/Users/login.ctp:21 -#: Template/Users/register.ctp:22 +#: templates/Users/add.php:25 +#: templates/Users/login.php:21 +#: templates/Users/register.php:22 msgid "Password" msgstr "" -#: Template/Users/add.ctp:26 -#: Template/Users/edit.ctp:38 -#: Template/Users/index.ctp:24 -#: Template/Users/register.ctp:27 +#: templates/Users/add.php:26 +#: templates/Users/edit.php:38 +#: templates/Users/index.php:24 +#: templates/Users/register.php:28 msgid "First name" msgstr "" -#: Template/Users/add.ctp:27 -#: Template/Users/edit.ctp:39 -#: Template/Users/index.ctp:25 -#: Template/Users/register.ctp:28 +#: templates/Users/add.php:27 +#: templates/Users/edit.php:39 +#: templates/Users/index.php:25 +#: templates/Users/register.php:29 msgid "Last name" msgstr "" -#: Template/Users/add.ctp:30 -#: Template/Users/edit.ctp:54 -#: Template/Users/view.ctp:49;74 +#: templates/Users/add.php:30 +#: templates/Users/edit.php:54 +#: templates/Users/view.php:49 +#: templates/Users/view.php:74 msgid "Active" msgstr "" -#: Template/Users/add.ctp:34 -#: Template/Users/change_password.ctp:25 -#: Template/Users/edit.ctp:58 -#: Template/Users/register.ctp:37 -#: Template/Users/request_reset_password.ctp:8 -#: Template/Users/resend_token_validation.ctp:20 -#: Template/Users/social_email.ctp:19 +#: templates/Users/add.php:34 +#: templates/Users/change_password.php:25 +#: templates/Users/edit.php:58 +#: templates/Users/register.php:38 +#: templates/Users/request_reset_password.php:23 +#: templates/Users/resend_token_validation.php:20 +#: templates/Users/social_email.php:19 msgid "Submit" msgstr "" -#: Template/Users/change_password.ctp:5 +#: templates/Users/change_password.php:5 msgid "Please enter the new password" msgstr "" -#: Template/Users/change_password.ctp:10 +#: templates/Users/change_password.php:10 msgid "Current password" msgstr "" -#: Template/Users/change_password.ctp:16 +#: templates/Users/change_password.php:16 msgid "New password" msgstr "" -#: Template/Users/change_password.ctp:21 -#: Template/Users/register.ctp:25 +#: templates/Users/change_password.php:21 +#: templates/Users/register.php:26 msgid "Confirm password" msgstr "" -#: Template/Users/edit.ctp:22 -#: Template/Users/index.ctp:40 +#: templates/Users/edit.php:22 +#: templates/Users/index.php:40 msgid "Delete" msgstr "" -#: Template/Users/edit.ctp:24 -#: Template/Users/index.ctp:40 -#: Template/Users/view.ctp:21 +#: templates/Users/edit.php:24 +#: templates/Users/index.php:40 +#: templates/Users/view.php:21 msgid "Are you sure you want to delete # {0}?" msgstr "" -#: Template/Users/edit.ctp:34 -#: Template/Users/view.ctp:17 +#: templates/Users/edit.php:34 +#: templates/Users/view.php:17 msgid "Edit User" msgstr "" -#: Template/Users/edit.ctp:40 -#: Template/Users/view.ctp:43 +#: templates/Users/edit.php:40 +#: templates/Users/view.php:43 msgid "Token" msgstr "" -#: Template/Users/edit.ctp:42 +#: templates/Users/edit.php:42 msgid "Token expires" msgstr "" -#: Template/Users/edit.ctp:45 +#: templates/Users/edit.php:45 msgid "API token" msgstr "" -#: Template/Users/edit.ctp:48 +#: templates/Users/edit.php:48 msgid "Activation date" msgstr "" -#: Template/Users/edit.ctp:51 +#: templates/Users/edit.php:51 msgid "TOS date" msgstr "" -#: Template/Users/edit.ctp:64 +#: templates/Users/edit.php:64 msgid "Reset Google Authenticator Token" msgstr "" -#: Template/Users/edit.ctp:70 +#: templates/Users/edit.php:70 msgid "Are you sure you want to reset token for user \"{0}\"?" msgstr "" -#: Template/Users/index.ctp:15 +#: templates/Users/index.php:15 msgid "New {0}" msgstr "" -#: Template/Users/index.ctp:37 +#: templates/Users/index.php:37 msgid "View" msgstr "" -#: Template/Users/index.ctp:38 +#: templates/Users/index.php:38 msgid "Change password" msgstr "" -#: Template/Users/index.ctp:39 +#: templates/Users/index.php:39 msgid "Edit" msgstr "" -#: Template/Users/index.ctp:49 +#: templates/Users/index.php:49 msgid "previous" msgstr "" -#: Template/Users/index.ctp:51 +#: templates/Users/index.php:51 msgid "next" msgstr "" -#: Template/Users/login.ctp:19 +#: templates/Users/login.php:19 msgid "Please enter your username and password" msgstr "" -#: Template/Users/login.ctp:29 +#: templates/Users/login.php:29 msgid "Remember me" msgstr "" -#: Template/Users/login.ctp:37 +#: templates/Users/login.php:37 msgid "Register" msgstr "" -#: Template/Users/login.ctp:43 +#: templates/Users/login.php:43 msgid "Reset Password" msgstr "" -#: Template/Users/login.ctp:48 +#: templates/Users/login.php:48 msgid "Login" msgstr "" -#: Template/Users/profile.ctp:21 +#: templates/Users/profile.php:21 msgid "{0} {1}" msgstr "" -#: Template/Users/profile.ctp:27 +#: templates/Users/profile.php:27 msgid "Change Password" msgstr "" -#: Template/Users/profile.ctp:38 -#: Template/Users/view.ctp:68 +#: templates/Users/profile.php:38 +#: templates/Users/view.php:68 msgid "Social Accounts" msgstr "" -#: Template/Users/profile.ctp:42 -#: Template/Users/view.ctp:73 +#: templates/Users/profile.php:42 +#: templates/Users/view.php:73 msgid "Avatar" msgstr "" -#: Template/Users/profile.ctp:43 -#: Template/Users/view.ctp:72 +#: templates/Users/profile.php:43 +#: templates/Users/view.php:72 msgid "Provider" msgstr "" -#: Template/Users/profile.ctp:44 +#: templates/Users/profile.php:44 msgid "Link" msgstr "" -#: Template/Users/profile.ctp:51 +#: templates/Users/profile.php:51 msgid "Link to {0}" msgstr "" -#: Template/Users/register.ctp:30 +#: templates/Users/register.php:31 msgid "Accept TOS conditions?" msgstr "" -#: Template/Users/request_reset_password.ctp:5 -msgid "Please enter your email to reset your password" +#: templates/Users/request_reset_password.php:20 +msgid "Please enter your email or username to reset your password" msgstr "" -#: Template/Users/resend_token_validation.ctp:15 +#: templates/Users/resend_token_validation.php:15 msgid "Resend Validation email" msgstr "" -#: Template/Users/resend_token_validation.ctp:17 +#: templates/Users/resend_token_validation.php:17 msgid "Email or username" msgstr "" -#: Template/Users/verify.ctp:13 +#: templates/Users/u2f_authenticate.php:22 +#: templates/Users/webauthn2fa.php:25 +msgid "Verify your registered yubico key" +msgstr "" + +#: templates/Users/u2f_authenticate.php:23 +#: templates/Users/u2f_register.php:23 +#: templates/Users/webauthn2fa.php:20 +#: templates/Users/webauthn2fa.php:26 +msgid "Please insert and tap your yubico key" +msgstr "" + +#: templates/Users/u2f_authenticate.php:24 +#: templates/Users/webauthn2fa.php:27 +msgid "You can now finish the authentication process using the registered device." +msgstr "" + +#: templates/Users/u2f_authenticate.php:25 +#: templates/Users/webauthn2fa.php:22 +#: templates/Users/webauthn2fa.php:28 +msgid "When the YubiKey starts blinking, press the golden disc to activate it. Depending on the web browser you might need to confirm the use of extended information from the YubiKey." +msgstr "" + +#: templates/Users/u2f_authenticate.php:27 +#: templates/Users/u2f_register.php:27 +#: templates/Users/webauthn2fa.php:31 +msgid "Reload" +msgstr "" + +#: templates/Users/u2f_authenticate.php:51 +#: templates/Users/u2f_register.php:56 +msgid "Yubico key check has failed, please try again" +msgstr "" + +#: templates/Users/u2f_register.php:22 +#: templates/Users/webauthn2fa.php:19 +msgid "Registering your yubico key" +msgstr "" + +#: templates/Users/verify.php:13 msgid "Verification Code" msgstr "" -#: Template/Users/verify.ctp:15 +#: templates/Users/verify.php:15 msgid " Verify" msgstr "" -#: Template/Users/view.ctp:19 +#: templates/Users/view.php:19 msgid "Delete User" msgstr "" -#: Template/Users/view.ctp:24 +#: templates/Users/view.php:24 msgid "New User" msgstr "" -#: Template/Users/view.ctp:31 +#: templates/Users/view.php:31 msgid "Id" msgstr "" -#: Template/Users/view.ctp:37 +#: templates/Users/view.php:37 msgid "First Name" msgstr "" -#: Template/Users/view.ctp:39 +#: templates/Users/view.php:39 msgid "Last Name" msgstr "" -#: Template/Users/view.ctp:41 +#: templates/Users/view.php:41 msgid "Role" msgstr "" -#: Template/Users/view.ctp:45 +#: templates/Users/view.php:45 msgid "Api Token" msgstr "" -#: Template/Users/view.ctp:53 +#: templates/Users/view.php:53 msgid "Token Expires" msgstr "" -#: Template/Users/view.ctp:55 +#: templates/Users/view.php:55 msgid "Activation Date" msgstr "" -#: Template/Users/view.ctp:57 +#: templates/Users/view.php:57 msgid "Tos Date" msgstr "" -#: Template/Users/view.ctp:59;75 +#: templates/Users/view.php:59 +#: templates/Users/view.php:75 msgid "Created" msgstr "" -#: Template/Users/view.ctp:61;76 +#: templates/Users/view.php:61 +#: templates/Users/view.php:76 msgid "Modified" msgstr "" -#: View/Helper/UserHelper.php:46 -msgid "Sign in with" +#: templates/Users/webauthn2fa.php:8 +msgid "Two-factor authentication" msgstr "" -#: View/Helper/UserHelper.php:103 -msgid "Logout" +#: templates/Users/webauthn2fa.php:21 +msgid "In order to enable your YubiKey the first step is to perform a registration." msgstr "" -#: View/Helper/UserHelper.php:121 -msgid "Welcome, {0}" +#: templates/email/html/reset_password.php:14 +#: templates/email/html/social_account_validation.php:14 +#: templates/email/html/validation.php:13 +#: templates/email/text/reset_password.php:12 +#: templates/email/text/social_account_validation.php:12 +#: templates/email/text/validation.php:12 +msgid "Hi {0}" msgstr "" -#: View/Helper/UserHelper.php:151 -msgid "reCaptcha is not configured! Please configure Users.reCaptcha.key" +#: templates/email/html/reset_password.php:17 +msgid "Reset your password here" msgstr "" -#: View/Helper/UserHelper.php:215 -msgid "Connected with {0}" +#: templates/email/html/reset_password.php:20 +#: templates/email/html/social_account_validation.php:23 +#: templates/email/html/validation.php:19 +msgid "If the link is not correctly displayed, please copy the following address in your web browser {0}" msgstr "" -#: View/Helper/UserHelper.php:220 -msgid "Connect with {0}" +#: templates/email/html/reset_password.php:27 +#: templates/email/html/social_account_validation.php:30 +#: templates/email/html/validation.php:26 +#: templates/email/text/reset_password.php:20 +#: templates/email/text/social_account_validation.php:20 +#: templates/email/text/validation.php:20 +msgid "Thank you" +msgstr "" + +#: templates/email/html/social_account_validation.php:18 +msgid "Activate your social login here" +msgstr "" + +#: templates/email/html/validation.php:16 +msgid "Activate your account here" +msgstr "" + +#: templates/email/text/reset_password.php:14 +#: templates/email/text/validation.php:14 +msgid "Please copy the following address in your web browser {0}" +msgstr "" + +#: templates/email/text/social_account_validation.php:14 +msgid "Please copy the following address in your web browser to activate your social login {0}" msgstr "" diff --git a/src/Controller/Traits/Webauthn2faTrait.php b/src/Controller/Traits/Webauthn2faTrait.php index 301c08acc..93f9fe313 100644 --- a/src/Controller/Traits/Webauthn2faTrait.php +++ b/src/Controller/Traits/Webauthn2faTrait.php @@ -74,7 +74,7 @@ public function webauthn2faRegister(): \Cake\Http\Response ); } catch (\Throwable $e) { $user = $this->request->getSession()->read('Webauthn2fa.User'); - Log::debug(__('Register error with webauthn for user id: {0}', $user['id'] ?? 'empty')); + Log::debug(__d('cake_d_c/users','Register error with webauthn for user id: {0}', $user['id'] ?? 'empty')); throw $e; } } @@ -119,7 +119,7 @@ public function webauthn2faAuthenticate(): \Cake\Http\Response ])); } catch (\Throwable $e) { $user = $this->request->getSession()->read('Webauthn2fa.User'); - Log::debug(__('Register error with webauthn for user id: {0}', $user['id'] ?? 'empty')); + Log::debug(__d('cake_d_c/users','Register error with webauthn for user id: {0}', $user['id'] ?? 'empty')); throw $e; } } diff --git a/src/Loader/AuthenticationServiceLoader.php b/src/Loader/AuthenticationServiceLoader.php index 5ef982860..efb81c728 100644 --- a/src/Loader/AuthenticationServiceLoader.php +++ b/src/Loader/AuthenticationServiceLoader.php @@ -106,7 +106,7 @@ protected function _getItemLoadData($item, $key) $options = $item; if (!isset($options['className'])) { throw new \InvalidArgumentException( - __('Property {0}.className should be defined', $key) + __d('cake_d_c/users','Property {0}.className should be defined', $key) ); } $className = $options['className']; diff --git a/templates/Users/u2f_authenticate.php b/templates/Users/u2f_authenticate.php index 5b48555de..16ce1bf01 100644 --- a/templates/Users/u2f_authenticate.php +++ b/templates/Users/u2f_authenticate.php @@ -21,7 +21,7 @@

-

+

Html->link( __d('cake_d_c/users', 'Reload'), diff --git a/templates/Users/webauthn2fa.php b/templates/Users/webauthn2fa.php index ae1686af0..3c2b7c898 100644 --- a/templates/Users/webauthn2fa.php +++ b/templates/Users/webauthn2fa.php @@ -5,7 +5,7 @@ * @var string $username */ $this->Html->script('CakeDC/Users.webauthn.js', ['block' => true]); -$this->assign('title', __('Two-factor authentication')); +$this->assign('title', __d('cake_d_c/users','Two-factor authentication')); ?>

@@ -28,7 +28,7 @@

Html->link( - __('Reload'), + __d('cake_d_c/users','Reload'), ['action' => 'webauthn2fa'], ['class' => 'btn btn-primary'] )?>

From 5d5176c3e1b8446c42adf6fa5b97ac126c912345 Mon Sep 17 00:00:00 2001 From: Kevin Pfeifer Date: Fri, 11 Mar 2022 14:32:28 +0100 Subject: [PATCH 683/685] fix CS problems --- src/Controller/Traits/Webauthn2faTrait.php | 4 ++-- src/Loader/AuthenticationServiceLoader.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Controller/Traits/Webauthn2faTrait.php b/src/Controller/Traits/Webauthn2faTrait.php index 93f9fe313..034a17442 100644 --- a/src/Controller/Traits/Webauthn2faTrait.php +++ b/src/Controller/Traits/Webauthn2faTrait.php @@ -74,7 +74,7 @@ public function webauthn2faRegister(): \Cake\Http\Response ); } catch (\Throwable $e) { $user = $this->request->getSession()->read('Webauthn2fa.User'); - Log::debug(__d('cake_d_c/users','Register error with webauthn for user id: {0}', $user['id'] ?? 'empty')); + Log::debug(__d('cake_d_c/users', 'Register error with webauthn for user id: {0}', $user['id'] ?? 'empty')); throw $e; } } @@ -119,7 +119,7 @@ public function webauthn2faAuthenticate(): \Cake\Http\Response ])); } catch (\Throwable $e) { $user = $this->request->getSession()->read('Webauthn2fa.User'); - Log::debug(__d('cake_d_c/users','Register error with webauthn for user id: {0}', $user['id'] ?? 'empty')); + Log::debug(__d('cake_d_c/users', 'Register error with webauthn for user id: {0}', $user['id'] ?? 'empty')); throw $e; } } diff --git a/src/Loader/AuthenticationServiceLoader.php b/src/Loader/AuthenticationServiceLoader.php index efb81c728..c4d2b6958 100644 --- a/src/Loader/AuthenticationServiceLoader.php +++ b/src/Loader/AuthenticationServiceLoader.php @@ -106,7 +106,7 @@ protected function _getItemLoadData($item, $key) $options = $item; if (!isset($options['className'])) { throw new \InvalidArgumentException( - __d('cake_d_c/users','Property {0}.className should be defined', $key) + __d('cake_d_c/users', 'Property {0}.className should be defined', $key) ); } $className = $options['className']; From 771805e337a3d50d96a998fc56d12fe520d070db Mon Sep 17 00:00:00 2001 From: Marcelo Rocha Date: Fri, 18 Mar 2022 12:24:39 -0300 Subject: [PATCH 684/685] Updated doc `Using the user's email to login` Updated doc `Using the user's email to login` to include required config for 'Remember me'. Related to issue #992 --- Docs/Documentation/Configuration.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Docs/Documentation/Configuration.md b/Docs/Documentation/Configuration.md index c502651e2..a7118a99b 100644 --- a/Docs/Documentation/Configuration.md +++ b/Docs/Documentation/Configuration.md @@ -174,6 +174,7 @@ user identify. Add this to your config/users.php: ```php 'Auth.Identifiers.Password.fields.username' => 'email', 'Auth.Authenticators.Form.fields.username' => 'email', +'Auth.Authenticators.Cookie.fields.username' => 'email', ``` * Override the login.php template to change the Form->control to "email". From b5993e1c65b99451869005542518e3f09fdfc4d3 Mon Sep 17 00:00:00 2001 From: TerryKern <56536101+TerryKern@users.noreply.github.com> Date: Mon, 21 Nov 2022 10:40:02 +0100 Subject: [PATCH 685/685] Correct casing of users.po in translation docs The users.po file which is used to overwrite the translations provided by the plugin should be lowercase. Seeing as though translation files are generally lowercase in CakePHP in addition to the fact that as soon as you deploy to a Linux environment this will bite you in the ass. --- Docs/Documentation/Translations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Documentation/Translations.md b/Docs/Documentation/Translations.md index 7576ed50e..d9cc74def 100644 --- a/Docs/Documentation/Translations.md +++ b/Docs/Documentation/Translations.md @@ -13,6 +13,6 @@ The Plugin is translated into several languages: * Turkish (tr_TR) by @sayinserdar * Ukrainian (uk) by @yarkm13 -**Note:** To overwrite the plugin translations, create a file inside your project 'resources/locales//{$lang}/' folder, with the name 'Users.po' and add the strings with the new translations. +**Note:** To overwrite the plugin translations, create a file inside your project 'resources/locales//{$lang}/' folder, with the name 'users.po' and add the strings with the new translations. Remember to clean the translations cache!
FacebookTwitterGoogleAmazonuser-1user-1@test.comfirst1last1user-66@example.comfirst-user-6firts name 6GoogleAmazonuser-1user-1@test.com